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.
- 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
| 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 | - |
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"] }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(())
}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(())
}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(())
}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(())
}Before using this library, register your application in the Azure Portal:
- Go to Azure Active Directory > App registrations > New registration
- Set a name and select supported account types
- 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
- Web apps:
- Note your Application (client) ID and Directory (tenant) ID
- For confidential clients: go to Certificates & secrets and create a client secret
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 | 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 |
This crate requires Rust 1.75 or later.
See CONTRIBUTING.md for guidelines.
See SECURITY.md for the security policy and how to report vulnerabilities.
This project is licensed under the MIT License.