azure_identity_gindix 0.21.0

Rust wrappers around Microsoft Azure REST APIs - Azure identity helper crate
Documentation
use azure_core::date;
use azure_identity::{authorization_code_flow, development::naive_redirect_server};
use oauth2::{ClientId, ClientSecret, TokenResponse};
use std::{
    env::{args, var},
    error::Error,
};
use time::OffsetDateTime;
use url::Url;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let client_id =
        ClientId::new(var("CLIENT_ID").expect("Missing CLIENT_ID environment variable."));
    let client_secret = ClientSecret::new(
        var("CLIENT_SECRET").expect("Missing CLIENT_SECRET environment variable."),
    );
    let tenant_id = var("TENANT_ID").expect("Missing TENANT_ID environment variable.");

    let storage_account_name = args()
        .nth(1)
        .expect("please specify the storage account name as first command line parameter");
    let container_name = args()
        .nth(2)
        .expect("please specify the container name as second command line parameter");

    // Create URL to browse for initial authorization
    let c = authorization_code_flow::start(
        client_id,
        Some(client_secret),
        &tenant_id,
        Url::parse("http://localhost:3003/redirect").unwrap(),
        &[&format!(
            "https://{storage_account_name}.blob.core.windows.net/user_impersonation"
        )],
    );

    println!("c == {c:?}");
    println!("\nbrowse this url:\n{}", c.authorize_url);

    // Start a naive redirect server to receive the redirect with the token.
    // This naive server is blocking so you should use something better.
    let code = naive_redirect_server(&c, 3003).unwrap();

    println!("code received: {code:?}");

    // Exchange the token with one that can be used for authorization
    let token = c
        .exchange(azure_core::new_http_client(), code)
        .await
        .unwrap();

    println!("token received: {token:?}");

    println!("token secret: {}", token.access_token().secret());

    let dt = OffsetDateTime::now_utc();
    let time = date::to_rfc1123(&dt);
    println!("x-ms-date ==> {time}");

    let resp = reqwest::Client::new()
        .get(&format!(
            "https://{storage_account_name}.blob.core.windows.net/{container_name}?restype=container&comp=list"
        ))
        .header(
            "Authorization",
            format!("Bearer {}", token.access_token().secret()),
        )
        .header("x-ms-version", "2019-07-07")
        .header("x-ms-date", time)
        .send()
        .await?
        .text()
        .await?;

    println!("\n\nresp {resp:?}");

    Ok(())
}