Migrate public client applications from ADAL.NET to MSAL.NET

This article describes how to migrate a public client application from Azure Active Directory Authentication Library for .NET (ADAL.NET) to Microsoft Authentication Library for .NET (MSAL.NET). Public client applications are desktop apps, including Win32, WPF, and UWP apps, and mobile apps, that call another service on the user's behalf. For more information about public client applications, see Authentication flows and application scenarios.

Migration steps

  1. Find the code by using ADAL.NET in your app.

    The code that uses ADAL in a public client application instantiates AuthenticationContext and calls an override of AcquireTokenAsync with the following parameters:

    • A resourceId string. This variable is the app ID URI of the web API that you want to call.
    • A clientId which is the identifier for your application, also known as App ID.
  2. After you've identified that you have apps that are using ADAL.NET, install the MSAL.NET NuGet package Microsoft.Identity.Client and update your project library references. For more information, see Install a NuGet package.

  3. Update the code according to the public client application scenario. Some steps are common and apply across all the public client scenarios. Other steps are unique to each scenario.

    The public client scenarios are:

Interactive scenarios are where your public client application shows a login user interface hosted in a browser, and the user is required to interactively sign-in.

Find out if your code uses interactive scenarios

The ADAL code for your app in a public client application that uses interactive authentication instantiates AuthenticationContext and includes a call to AcquireTokenAsync, with the following parameters.

  • A clientId which is a GUID representing your application registration
  • A resourceUrl which indicates the resource you are asking the token for
  • A URI that is the reply URL
  • A PlatformParameters object.

Update the code for interactive scenarios

The following steps for updating code apply across all the confidential client scenarios:

  1. Add the MSAL.NET namespace in your source code: using Microsoft.Identity.Client;.
  2. Instead of instantiating AuthenticationContext, use PublicClientApplicationBuilder.Create to instantiate IPublicClientApplication.
  3. Instead of the resourceId string, MSAL.NET uses scopes. Because applications that use ADAL.NET are preauthorized, you can always use the following scopes: new string[] { $"{resourceId}/.default" }.
  4. Replace the call to AuthenticationContext.AcquireTokenAsync with a call to IPublicClientApplication.AcquireTokenXXX, where XXX depends on your scenario.

In this case, we replace the call to AuthenticationContext.AcquireTokenAsync with a call to IPublicClientApplication.AcquireTokenInteractive.

Here's a comparison of ADAL.NET and MSAL.NET code for interactive scenarios:

ADAL

MSAL

var ac = new AuthenticationContext("https://login.microsoftonline.com/<tenantId>");
AuthenticationResult result;
result = await ac.AcquireTokenAsync("<clientId>",
"https://resourceUrl",
new Uri("https://ClientReplyUrl"),
new PlatformParameters(PromptBehavior.Auto));
// 1. Configuration - read below about redirect URI
var pca = PublicClientApplicationBuilder.Create("client_id")
.WithBroker()
.Build();

// Add a token cache, see https://learn.microsoft.com/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=desktop

// 2. GetAccounts
var accounts = await pca.GetAccountsAsync();
var accountToLogin = // choose an account, or null, or use PublicClientApplication.OperatingSystemAccount for the default OS account

try
{
// 3. AcquireTokenSilent 
var authResult = await pca.AcquireTokenSilent(new[] { "User.Read" }, accountToLogin)
.ExecuteAsync();
}
catch (MsalUiRequiredException) // no change in the pattern
{
// 4. Specific: Switch to the UI thread for next call . Not required for console apps.
await SwitchToUiThreadAsync(); // not actual code, this is different on each platform / tech

// 5. AcquireTokenInteractive
var authResult = await pca.AcquireTokenInteractive(new[] { "User.Read" })
.WithAccount(accountToLogin)  // this already exists in MSAL, but it is more important for WAM
.WithParentActivityOrWindow(myWindowHandle) // to be able to parent WAM's windows to your app (optional, but highly recommended; not needed on UWP)
.ExecuteAsync();
}

The MSAL code shown above uses WAM (Web authentication manager) which is the recommended approach. If you wish to use interactive authentication without WAM, see Interactive Authentication.

MSAL benefits

Key benefits of MSAL.NET for your app include:

  • Resilience. MSAL.NET helps make your app resilient through the following:

    • Microsoft Entra ID Cached Credential Service (CCS) benefits. CCS operates as a Microsoft Entra backup.
    • Proactive renewal of tokens if the API that you call enables long-lived tokens through continuous access evaluation.

Troubleshooting

The following troubleshooting information makes two assumptions:

  • Your ADAL.NET code was working.
  • You migrated to MSAL by keeping the same client ID.

If you get an exception with either of the following messages:

AADSTS90002: Tenant 'cf61953b-e41a-46b3-b500-663d279ea744' not found. This may happen if there are no active subscriptions for the tenant. Check to make sure you have the correct tenant ID. Check with your subscription administrator.

You can troubleshoot the exception by using these steps:

  1. Confirm that you're using the latest version of MSAL.NET.
  2. Confirm that the authority host that you set when building the confidential client application and the authority host that you used with ADAL are similar. In particular, is it the same cloud (Azure Government, Microsoft Azure operated by 21Vianet, or Azure Germany)?

Next steps

Learn more about the differences between ADAL.NET and MSAL.NET apps. Learn more about token cache serialization in MSAL.NET