Skip to content

tolgaki/msal-rust

Repository files navigation

Microsoft Authentication Library (MSAL) for Rust

Crates.io Documentation License: MIT CI

A Rust implementation of the Microsoft Authentication Library (MSAL), enabling authentication with the Microsoft identity platform (Azure AD, Microsoft personal accounts, Azure AD B2C).

This crate is part of the MSAL family of libraries alongside msal-js, MSAL.NET, MSAL Python, MSAL Java, and MSAL Go.

Features

  • Public client authentication for desktop apps, CLI tools, and devices
  • Confidential client authentication for web apps, daemons, and APIs
  • Brokered authentication via Windows WAM and macOS Enterprise SSO for device-bound tokens and system-wide SSO
  • In-memory token cache with automatic expiration handling
  • Authority discovery via OpenID Connect metadata
  • Support for Azure AD, Azure AD B2C, ADFS, and CIAM authorities
  • Fully async with Tokio

Supported Authentication Flows

Flow Public Confidential
Authorization Code (PKCE) Yes Yes
Device Code Yes -
Client Credentials - Yes
On-Behalf-Of - Yes
Refresh Token Yes Yes
Silent (cache + refresh) Yes Yes
Username/Password (ROPC) Yes -
Interactive (native broker) Yes -

Installation

Add to your Cargo.toml:

[dependencies]
msal = "0.1"
tokio = { version = "1", features = ["full"] }

For native broker support:

# Windows (Web Account Manager)
msal = { version = "0.1", features = ["broker-wam"] }

# macOS (Enterprise SSO plug-in)
msal = { version = "0.1", features = ["broker-macos"] }

Quick Start

Device Code Flow (CLI apps)

use msal::{Configuration, PublicClientApplication};
use msal::request::DeviceCodeRequest;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Configuration::builder("your-client-id")
        .authority("https://login.microsoftonline.com/common")
        .build();

    let app = PublicClientApplication::new(config)?;

    let result = app
        .acquire_token_by_device_code(
            DeviceCodeRequest::new(vec!["user.read".into()]),
            |info| println!("{}", info.message),
        )
        .await?;

    println!("Signed in, access token: {}...", &result.access_token[..20]);
    Ok(())
}

Client Credentials (Daemons / Services)

use msal::{Configuration, ConfidentialClientApplication};
use msal::request::ClientCredentialRequest;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Configuration::builder("your-client-id")
        .authority("https://login.microsoftonline.com/your-tenant-id")
        .client_secret("your-client-secret")
        .build();

    let app = ConfidentialClientApplication::new(config)?;

    let request = ClientCredentialRequest::new(
        vec!["https://graph.microsoft.com/.default".into()],
    );

    let result = app.acquire_token_by_client_credential(request).await?;
    println!("Token: {}...", &result.access_token[..20]);
    Ok(())
}

Authorization Code Flow (Web Apps)

use msal::{Configuration, PublicClientApplication};
use msal::request::{AuthorizationCodeRequest, SilentFlowRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Configuration::builder("your-client-id")
        .authority("https://login.microsoftonline.com/common")
        .build();

    let app = PublicClientApplication::new(config)?;

    // Step 1: Generate the authorization URL (synchronous).
    let scopes = vec!["user.read".into()];
    let (auth_url, pkce) = app.authorization_url(
        &scopes,
        "http://localhost:3000/redirect",
        None,
    )?;

    println!("Visit: {auth_url}");

    // Step 2: Exchange the authorization code.
    let mut request = AuthorizationCodeRequest::new(
        "code-from-redirect".into(),
        scopes.clone(),
        "http://localhost:3000/redirect".into(),
    );
    request.code_verifier = Some(pkce.verifier);

    let result = app.acquire_token_by_code(request).await?;
    println!("Signed in as: {}", result.account.unwrap().username);

    // Step 3: Silent token renewal (from cache or refresh token).
    // let silent = SilentFlowRequest::new(scopes, account);
    // let cached = app.acquire_token_silent(silent).await?;
    Ok(())
}

Brokered Authentication (Windows / macOS)

use msal::{Configuration, PublicClientApplication};
use msal::broker::BrokerTokenRequest;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Configuration::builder("your-client-id")
        .authority("https://login.microsoftonline.com/your-tenant-id")
        .build();

    let app = PublicClientApplication::new(config)?;

    // Set up the platform-specific broker.
    #[cfg(all(target_os = "windows", feature = "broker-wam"))]
    {
        let broker = msal::broker::wam::WamBroker::new().await?;
        app.set_broker(Box::new(broker)).await;
    }
    #[cfg(all(target_os = "macos", feature = "broker-macos"))]
    {
        // For CLI tools (unsigned binaries):
        let broker = msal::broker::macos::MacOsBroker::new_for_cli(
            "https://login.microsoftonline.com/your-tenant-id",
        )?;
        // For .app bundles, use MacOsBroker::new("msauth.{bundle_id}://auth", authority)
        app.set_broker(Box::new(broker)).await;
    }

    let request = BrokerTokenRequest {
        scopes: vec!["user.read".into()],
        account: None,
        claims: None,
        correlation_id: None,
        window_handle: None,
        authentication_scheme: Default::default(),
        pop_params: None,
    };

    let result = app.acquire_token_interactive(request).await?;
    println!("Token: {}...", &result.access_token[..20]);
    Ok(())
}

Azure App Registration

Before using this library, register your application in the Azure Portal:

  1. Go to Azure Active Directory > App registrations > New registration
  2. Set a name and select supported account types
  3. Set a redirect URI:
    • Web apps: http://localhost:3000/redirect
    • WAM broker: ms-appx-web://Microsoft.AAD.BrokerPlugin/{client_id}
    • macOS broker: msauth.{bundle_id}://auth
  4. Note your Application (client) ID and Directory (tenant) ID
  5. For confidential clients: go to Certificates & secrets and create a client secret

Architecture

msal (crate root)
 +-- config         Configuration builder
 +-- client
 |    +-- public         PublicClientApplication (user flows)
 |    +-- confidential   ConfidentialClientApplication (app flows)
 +-- broker
 |    +-- mod            NativeBroker trait
 |    +-- wam            Windows WAM (feature: broker-wam)
 |    +-- macos          macOS Enterprise SSO (feature: broker-macos)
 +-- authority       Authority resolution and OpenID discovery
 +-- cache           In-memory token cache
 +-- account         AccountInfo, IdTokenClaims, ClientInfo
 +-- request         Request parameter types for each flow
 +-- response        AuthenticationResult, TokenResponse
 +-- crypto          PKCE, nonce generation, JWT decoding
 +-- error           MsalError enum

Feature Flags

Feature Default Platform Description
broker-wam No Windows Web Account Manager for device-bound tokens and SSO
broker-macos No macOS Enterprise SSO plug-in via Company Portal

Minimum Supported Rust Version (MSRV)

This crate requires Rust 1.75 or later.

Contributing

See CONTRIBUTING.md for guidelines.

Security

See SECURITY.md for the security policy and how to report vulnerabilities.

License

This project is licensed under the MIT License.

About

Microsoft Authentication Library (MSAL) for Rust

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages