Adal to Msal

Jean-Marc Prieur edited this page Oct 17, 2018 · 37 revisions

Differences between ADAL.NET and MSAL.NET applications

Choosing between ADAL.NET (Azure AD v1.0) and MSAL.NET (Azure AD v2.0)

See choosing between ADAL.NET (Azure AD v1.0) and MSAL.NET (Azure AD v2.0) to understand why you might want to use MSAL.NET instead of ADAL.NET, and the current constraints.

If you are already familiar with the v1.0 endpoint (and ADAL.NET), you might want to read What's different about the v2.0 endpoint?

Differences between ADAL.NET (Azure AD v1.0) and MSAL.NET (Azure AD v2.0) apps

Overview of the differences

The picture below summarizes some of the differences between ADAL.NET and MSAL.NET sideBySideCodeAdalMsal


NuGet packages and Namespaces

ADAL.NET is consumed from the Microsoft.IdentityModel.Clients.ActiveDirectory NuGet package. the namespace to use is Microsoft.IdentityModel.Clients.ActiveDirectory.

To use MSAL.NET you will need to add the Microsoft.Identity.Client NuGet package (for the moment in Preview), and use the Microsoft.Identity.Client namespace

Scopes not resources

Whereas ADAL.NET acquires token for resources, MSAL.NET acquires them for scopes. A number of MSAL.NET AcquireToken overrides require a parameter called scopes(IEnumerable<string> scopes). This parameter is a simple list of strings that declare the desired permissions and resources that are requested. Well known scopes are the Microsoft Graph's scopes.

It's also possible in MSAL.NET to access v1.0 resources. See details in Scopes for a v1.0 application below

Core classes

  • ADAL.NET uses AuthenticationContext as the representation of your connection to the Security Token Service (STS) or authorization server, through an Authority. On the contrary, MSAL.NET is designed around client applications. It provides two separate classes PublicClientApplication and ConfidentialClientApplication

  • Acquiring Tokens: ADAL.NET and MSAL.NET have the same authentication calls (AcquireTokenAsync and AcquireTokenSilentAsync) but with different parameters required. One difference is the fact that, in MSAL.NET, you no longer have to pass in the ClientID of your application in every AcquireTokenXX call. Indeed, the ClientID is set only once when calling the constructor of the (PublicClientApplication or ConfidentialClientApplication.

IAccount not IUser

ADAL.NET manipulated users. However, a user is a human or a software agent, but it can possess/own/be responsible for one or more accounts in the Microsoft identity system (several Azure AD accounts, Azure AD B2C, Microsoft personal accounts).

MSAL.NET 2.x now defines the notion of Account (through the IAccount interface). This breaking change provides the right semantics: the fact that the same user can have several accounts, in different Azure AD directories. Also MSAL.NET provides better information in the case of guest scenarios, as home account information is provided.

For more information about the differences between IUser and IAccount see


Interaction required exceptions

MSAL.NET has more explicit exceptions. For example: when silent authentication fails in ADAL, the current procedure is to catch the exception and look for the “user_interaction_required” error code:


catch(AdalException exception)
 if (exception.ErrorCode == ““user_interaction_required”)
  {“try to authenticate interactively”}}

See details in The recommended pattern to acquire a token with ADAL.NET

In MSAL.NET, you can catch MsalUiRequiredException as described in AcquireTokenSilentAsync

catch(MsalUiRequiredException exception)
 Try {“try to authenticate interactively”}
Handling Claim challenge exceptions
How ADAL.NET does it?
  • AdalClaimChallengeException is an exception (deriving from AdalServiceException) thrown by the service in case a resource requires more claims from the user (for instance two-factors authentication). The Claims member contains some json fragment with the claims, which are expected.
  • Still in ADAL.NET, the public client application receiving this exception needs to call the AcquireTokenAsync override having a claims parameter. This override of AcquireTokenAsync does not even try to hit the cache, it’s necessarily interactive. The reason is that the token in the cache does not have the right claims (otherwise an AdalClaimChallengeException would not have been thrown). Therefore, there is no need looking at the cache. Note that the ClaimChallengeException can be received in a WebAPI doing OBO, whereas the AcquireTokenAsync needs to be called in a public client application calling this Web API.
  • for details, including samples see Handling AdalClaimChallengeException
How to handle claim challenge exceptions in MSAL.NET?
  • The Claims are surfaced in the MsalServiceException.
  • Almost all the AcquireTokenAsync overrides in MSAL.NET all have extraQueryParameters parameter. The way to go today is to add $"&claims={msalServiceException.Claims}” to the current extraQueryParameters.

Supported grants

Not all the grants are yet supported in MSAL.NET / the AAD v2.0 endpoint. Here is a summary comparing ADAL.NET and MSAL.NET's supported grants

Public client applications

Here are the grants supported in ADAL.NET and MSAL.NET for Desktop and Mobile applications

Interactive Interactive Auth Acquiring tokens interactively in MSAL.NET
Integrated Windows Authentication AcquireTokenSilentAsync using Integrated authentication on Windows (Kerberos) Integrated Windows Authentication
Username / Password Acquiring tokens with username and password Username Password Authentication
Device code flow Device profile for devices without web browsers Device Code flow
Confidential client applications

Here are the grants supported in ADAL.NET and MSAL.NET for Web Applications, Web APIs, and daemon applications:

Type of App Grant ADAL.NET MSAL.NET
Web App, Web API, daemon Client Credentials Client credential flows in ADAL.NET Client credential flows in MSAL.NET
Web API On behalf of Service to service calls on behalf of the user with ADAL.NET On behalf of in MSAL.NET
Web App Auth Code Acquiring tokens with authorization codes on web apps with ADAL.NET Acquiring tokens with authorization codes on web apps with A MSAL.NET

Cache persistence

ADAL.NET allows you to extend the TokenCache class to implement the desired persistence functionality on platforms without a secure storage (.NET Framework and .NET core) by using the BeforeAccess, AfterAccess and BeforeWrite methods. For details, see Token Cache Serialization in ADAL.NET.

MSAL.NET makes the token cache a sealed class, removing the ability to extend it. Therefore, your implementation of token cache persistence must be in the form of a helper class that interacts with the sealed token cache. This interaction is described in Token Cache Serialization in MSAL.NET

Signification of the common authority

In v1.0, if you use the authority, you will allow users to sign in with any AAD account (for any organization). See Authority Validation in ADAL.NET

If you use the authority in v2.0, you will allow users to sign in with any AAD organization or a Microsoft personal account (MSA). In MSAL.NET, if you want to restrict login to any AAD account (same behavior as with ADAL.NET), you need to use For details, see the authority parameter in public client application.

Scopes for a v1.0 application

OAuth2 permissions are permission scopes that a v1.0 web API (resource) application exposes to client applications. These permission scopes may be granted to client applications during consent. See the section about oauth2Permissions in the Azure Active Directory application manifest article

Scopes to request access to specific OAuth2 permissions of a v1.0 application

if you want to acquire tokens for specific scopes of a v1.0 application (for instance the AAD graph, which is, you'd need to create scopes by concatenating a desired resource identifier with a desired OAuth2 permission for that resource.

For instance, to access, in the name of the user, a v1.0 Web API which App ID URI is ResourceId, you'd want to use:

var scopes = new [] {  ResourceId+"/user_impersonation"};

If you want to read and write with MSAL.NET Azure Active Directory using the AAD graph API (, you would create a list of scopes like in the following snippet:

ResourceId = "";
var scopes = new [] { ResourceId +Directory.Read”, ResourceID +Directory.Write”}
Warning: Special case of Azure Resource Manager (

There is one exception, which is the Azure Resource Manager API ( which expects a slash on the API name, and then there is a slash to separate it from the scope. Therefore it requires you to have two slashes:

var scopes = new[] {""};
var result = await app.AcquireTokenAsync(scopes);

// then call the API:

Scopes to request access to all the permissions of a v1.0 application

For instance, if you want to acquire a token for all the static scopes of a v1.0 application, one would need to use

ResourceId = "someAppIDURI";
var scopes = new [] {  ResourceId+"/.default"};

Scopes to request in the case of client credential flow / daemon app

In the case of client credential flow, the scope to pass would also be /.default. This tells to Azure AD: "all the app-level permissions that the admin has consented to in the application registration.

More information

you can find more information about the scopes in Scopes, permissions, and consent in the Azure Active Directory v2.0 endpoint

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.