-
Notifications
You must be signed in to change notification settings - Fork 366
Client credential flows
MSAL is a multi-framework library. Confidential Client flows are not available on the mobile platforms (UWP, Xamarin.iOS, and Xamarin.Android) since there is no secure way of deploying a secret there.
MSAL.NET supports 2 types of client credentials, which must be registered in the AAD app registration portal
- Application secrets (not recommended for production scenarios)
- Certificates
For advanced scenarios, 2 more types of credentials can be used. See details at Client assertions.
- Signed client assertions
- Certificate + additional claims to be sent
// this object will cache tokens in-memory - keep it as a singleton
var singletonApp = ConfidentialClientApplicationBuilder.Create(config.ClientId)
// don't specify authority here, we'll do it on the request
.WithCertificate(certificate) // or .WithSecret(secret)
.Build();
// If instead you need to re-create the ConfidentialClientApplication on each request, you MUST customize
// the cache serialization (see below)
// when making the request, specify the tenanted authority
var authResult = await app.AcquireTokenForClient(scopes: new [] { "some_app_id_uri/.default"}) // uses the token cache automatically, which is optimized for multi-tenant access
.WithAuthority(AzureCloudInstance.AzurePublic, "{tenantID}") // do not use "common" or "organizations"!
.ExecuteAsync();
For more information, see AuthenticationConfig.cs
Important: Token cache performance was significantly improved in MSAL 4.30
If your service is multi-tenant (i.e. it needs tokens for a resource that is in different tenants), see MSAL for client credential flow in multi-tenant services.
You can serialize the token cache to a location of your choice for example in-memory or in distributed location like Redis. You would do this to:
- share the token cache between several instances of ConfidentialClientApplication OR
- persist the token cache to Redis to share it between different machines
Please see distributed cache implementations and binding the token cache.
This sample shows token cache serialization.
Problem: My service is running out of memory. Solution: See MSAL for client credential flow in multi-tenant services. Provision enough RAM on the machines running your service or use a distributed cache. A single token is a only a few KB in size, but there is 1 token for each tenant! A multi-tenant service sometimes needs tokens for 0.5M tenants.
Problem: How can I avoid requesting new tokens on each machine of my distributed service? Solution: Use a distributed cache like Redis.
Problem: I customized my cache. How can I monitor the hit rate? Solution: The result object will tell you if the token comes from the cache or not:
authResult.AuthenticationResultMetadata.TokenSource == TokenSource.Cache
Problem: I am getting "loop detected" errors Solution: You are calling AAD for a token to often and AAD is throttling you. You need to use a cache - either the in-memory one (as per the sample above) or a persisted one.
Problem: AcquireTokenClient
latency is too high
Possible Solutions: Please ensure you have a high token cache hit rate.
The in-memory cache is optimized for searching through tokens that come from different client_id or different tenant_id. It is not optimized for storing tokens with different scopes. You need to use a different cache key that includes the scope. See https://aka.ms/msal-net-performance-testing
You can register your application secrets either through the interactive experience in the Azure portal, or using command-line tools (like PowerShell)
The management of client credentials happens in the certificates & secrets page for an application:
The active-directory-dotnetcore-daemon-v2 sample shows how to register an application secret or a certificate with an Azure AD application:
- For details on how to register an application secret, see AppCreationScripts/Configure.ps1
- For details on how to register a certificate with the application, see AppCreationScripts-withCert/Configure.ps1
In MSAL.NET client credentials are passed as a parameter at the application construction
Then, once the confidential client application is constructed, acquiring the token is a question of calling overrides of AcquireTokenForClient
, passing the scope, and forcing or not a refresh of the token.
Instead of a client secret or a certificate, the confidential client application can also prove its identity using client assertions. This advanced scenario is detailed in Client assertions
AcquireTokenForClient
uses the application token cache (not the user token cache)
Don't call AcquireTokenSilent
before calling AcquireTokenForClient
as AcquireTokenSilent
uses the user token cache. AcquireTokenForClient
checks the application token cache itself and updates it.
The scope to request for a client credential flow is the name of the resource followed by /.default
. This notation tells Azure AD to use the application level permissions declared statically during the application registration. Also these API permissions must be granted by a tenant administrator
ResourceId = "someAppIDURI";
var scopes = new [] { ResourceId+"/.default"};
var result = app.AcquireTokenForClient(scopes);
In the case where your confidential client application uses only client credentials flow, you don't need to pass a reply URL passed in the constructor.
Sample | Platform | Description |
---|---|---|
active-directory-dotnetcore-daemon-v2 | .NET Core 2.1 Console |
A simple .NET Core application that displays the users of a tenant querying the Microsoft Graph using the identity of the application, instead of on behalf of a user. ![]() The sample also illustrates the variation with certificates. ![]() |
active-directory-dotnet-daemon-v2 | ASP.NET MVC |
A web application that sync's data from the Microsoft Graph using the identity of the application, instead of on behalf of a user. ![]() |
You can find more information in:
- The reference documentation for ConfidentialClientApplication Constructors and AcquireTokenForClientAsync
- The protocol documentation: Azure Active Directory v2.0 and the OAuth 2.0 client credentials flow
Vanity URL: https://aka.ms/msal-net-client-credentials
- Home
- Why use MSAL.NET
- Is MSAL.NET right for me
- Scenarios
- Register your app with AAD
- Client applications
- Acquiring tokens
- MSAL samples
- Known Issues
- Acquiring a token for the app
- Acquiring a token on behalf of a user in Web APIs
- Acquiring a token by authorization code in Web Apps
- AcquireTokenInteractive
- WAM - the Windows broker
- .NET Core
- Maui Docs
- Custom Browser
- Applying an AAD B2C policy
- Integrated Windows Authentication for domain or AAD joined machines
- Username / Password
- Device Code Flow for devices without a Web browser
- ADFS support
- High Availability
- Regional
- Token cache serialization
- Logging
- Exceptions in MSAL
- Provide your own Httpclient and proxy
- Extensibility Points
- Clearing the cache
- Client Credentials Multi-Tenant guidance
- Performance perspectives
- Differences between ADAL.NET and MSAL.NET Apps
- PowerShell support
- Testing apps that use MSAL
- Experimental Features
- Proof of Possession (PoP) tokens
- Using in Azure functions
- Extract info from WWW-Authenticate headers
- SPA Authorization Code