你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将公共客户端应用程序从 ADAL.NET 迁移到 MSAL.NET

本文介绍如何将公共客户端应用程序从适用于 .NET 的 Azure Active Directory 身份验证库 (ADAL.NET) 迁移到适用于 .NET 的 Microsoft 身份验证库 (MSAL.NET)。 公共客户端应用程序是桌面应用,包括代表用户调用其他服务的 Win32、WPF、UWP 和移动应用。 有关公共客户端应用程序的详细信息,请参阅身份验证流和应用程序方案

迁移步骤

  1. 在应用中使用 ADAL.NET 查找代码。

    公共客户端应用程序中使用 ADAL 的代码将会通过以下参数实例化 AuthenticationContext 并调用 AcquireTokenAsync 的重写:

    • resourceId 字符串。 此变量是要调用的 Web API 的应用 ID URI。
    • 一个 clientId,即应用程序的标识符,也称为应用 ID。
  2. 确定有应用使用 ADAL.NET 后,安装 MSAL.NET NuGet 包 Microsoft.Identity.Client 并更新项目库引用。 有关详细信息,请参阅安装 NuGet 包

  3. 根据公共客户端应用程序方案更新代码。 有些步骤是通用的,适用于所有公共客户端方案。 其他步骤对每种场景具有唯一性。

    公共客户端方案包括:

    • Web 身份验证管理器,Windows 上首选的基于代理的身份验证。
    • 交互式身份验证,其中会向用户显示一个基于 Web 的界面用于完成登录过程。
    • 集成 Windows 身份验证,用户使用他们在登录到 Windows 域时所用的相同标识进行登录(适用于已加入域或已加入 Azure AD 的计算机)。
    • 用户名/密码,通过提供用户名/密码凭据进行登录。
    • 设备代码流,在其中,UX 受限的设备会显示一个设备代码,以便在备用设备上完成身份验证流。

在交互式方案中,公共客户端应用程序将显示托管在浏览器中的登录用户界面,并要求用户以交互方式登录。

确定代码是否使用交互式方案

在使用交互式身份验证的公共客户端应用程序中,应用的 ADAL 代码将会通过以下参数实例化 AuthenticationContext 并包含对 AcquireTokenAsync 的调用。

  • 一个 clientId,即表示应用程序注册的 GUID
  • 一个 resourceUrl,表示要请求其令牌的资源
  • 一个表示回复 URL 的 URI
  • PlatformParameters 对象。

更新交互式方案的代码

以下用于更新代码的步骤适用于所有机密客户端方案:

  1. 在源代码中使用 MSAL.NET 命名空间:using Microsoft.Identity.Client;
  2. 使用 PublicClientApplicationBuilder.Create 实例化 IPublicClientApplication,而不是实例化 AuthenticationContext
  3. MSAL.NET 使用作用域,而不是字符串 resourceId。 由于使用 ADAL.NET 的应用程序是预先授权的,因此可以始终使用以下作用域:new string[] { $"{resourceId}/.default" }
  4. 将对 AuthenticationContext.AcquireTokenAsync 的调用替换为对 IPublicClientApplication.AcquireTokenXXX 的调用,其中 XXX 取决于你的方案。

在这种情况下,我们使用对 IPublicClientApplication.AcquireTokenInteractive 的调用替换对 AuthenticationContext.AcquireTokenAsync 的调用。

下面是交互式方案的 ADAL.NET 和 MSAL.NET 代码的比较:

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();
}

上面所示的 MSAL 代码使用 WAM(Web 身份验证管理器),这是建议的方法。 如果你想要使用交互式身份验证但不使用 WAM,请参阅交互式身份验证

MSAL 优势

对于应用来说,MSAL.NET 的主要优势包括:

  • 复原能力。 MSAL.NET 可通过以下方面帮助应用实现可复原性:

    • Azure AD 缓存凭据服务 (CCS) 优势。 CCS 以 Azure AD 备份的形式操作。
    • 如果调用的 API 通过连续访问评估启用了长效令牌,则主动更新令牌。

故障排除

以下故障排除信息提出两种假设:

  • 你的 ADAL.NET 代码正常运行。
  • 你通过保留同一客户端 ID 迁移到 MSAL。

如果通过以下任一消息遇到异常:

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.

可以使用以下步骤对异常进行故障排除:

  1. 确认使用的是最新版本的 MSAL.NET。
  2. 确认在生产机密客户端应用程序时设置的授权主机与使用 ADAL 时使用的授权主机类似。 具体而言,这是否为同一种(Azure 政府、Azure 中国世纪互联或 Azure 德国)?

后续步骤

详细了解 ADAL.NET 与 MSAL.NET 应用之间的差异。 详细了解 MSAL.NET 中的令牌缓存序列化