适用于Java的 ADAL 到 MSAL 迁移指南

本文重点介绍了将使用Azure Active Directory身份验证库(ADAL)的应用程序迁移到Microsoft 身份验证库(MSAL)时需要做出的更改。

用于 Java 的 Microsoft 身份验证库(MSAL4J)和用于 Java 的 Azure AD 身份验证库(ADAL4J)用于对Microsoft Entra实体进行身份验证,并从Microsoft Entra ID请求令牌。 到目前为止,大多数开发人员都使用 Azure AD,以便开发人员(v1.0)使用各种标识(例如工作和学校帐户)进行身份验证,方法是使用 Azure AD 身份验证库(ADAL)请求令牌。

MSAL 具有以下优势:

  • 由于它使用的是较新的 Microsoft 标识平台,因此你可以对更广泛的一组 Microsoft 标识进行身份验证,例如通过 Azure AD Business to Consumer (Azure AD B2C) 进行身份验证的 Microsoft Entra 标识、Microsoft 帐户、社交帐户和本地帐户,以及通过 Microsoft Entra 外部 ID 进行身份验证的社交或本地客户帐户。
  • 你的用户将获得最佳的单一登录体验。
  • 应用程序可以启用增量许可,并支持新功能,例如条件访问。

MSAL for Java 是我们建议与 Microsoft 标识平台配合使用的身份验证库。 ADAL4J 上不会实现任何新功能。 今后所做的一切努力都集中在改进 MSAL 上。

可以了解有关 MSAL 的详细信息,并开始使用Microsoft 身份验证库

范围不是资源

ADAL4J 为资源获取令牌,而 MSAL for Java 为作用域获取令牌。 许多用于Java类的 MSAL 都需要范围参数。 此参数是一个字符串列表,用于声明所请求的权限和资源。 请参阅Microsoft Graph的范围以查看示例范围。

可以将范围后缀添加到 /.default 资源,以帮助将应用从 ADAL 迁移到 MSAL。 例如,对于资源值 https://graph.microsoft.com,等效的范围值为 https://graph.microsoft.com/.default。 如果资源不是 URL 形式,而是采用 XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX 这种形式的资源 ID,则仍然可以将 scope 值设为 XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/.default

有关不同类型的作用域的详细信息,请参阅Microsoft 标识平台中的权限和许可以及接受 v1.0 令牌的 Web API 的作用域这两篇文章。

核心类

在 ADAL4J 中,AuthenticationContext 类表示你通过 Authority 与安全令牌服务(STS)或授权服务器建立的连接。 但是,适用于Java的 MSAL 围绕客户端应用程序进行设计。 它提供两个单独的类: PublicClientApplicationConfidentialClientApplication 表示客户端应用程序。 后者 ConfidentialClientApplication表示一个应用程序,旨在安全地维护机密,例如守护程序应用的应用程序标识符。

下表显示了 ADAL4J 函数如何映射到Java函数的新 MSAL:

ADAL4J 方法 MSAL4J 方法
acquireToken(String resource, ClientCredential credential, AuthenticationCallback callback) ClientCredentialParameters
acquireToken(String resource, ClientAssertion assertion, AuthenticationCallback callback) ClientCredentialParameters
acquireToken(String resource, AsymmetricKeyCredential credential, AuthenticationCallback callback) ClientCredentialParameters
acquireToken(String resource, String clientId, String username, String password, AuthenticationCallback callback) UserNamePasswordParameters
acquireToken(String resource, String clientId, String username, String password=null, AuthenticationCallback callback) IntegratedWindowsAuthenticationParameters
acquireToken(String resource, UserAssertion userAssertion, ClientCredential credential, AuthenticationCallback callback) OnBehalfOfParameters
acquireTokenByAuthorizationCode() AuthorizationCodeParameters
acquireDeviceCode() and acquireTokenByDeviceCode() DeviceCodeFlowParameters
acquireTokenByRefreshToken() SilentParameters

用 IAccount 代替 IUser

ADAL4J 管理用户。 尽管用户表示单个人类或软件代理,但它可以在Microsoft标识系统中拥有一个或多个帐户。 例如,用户可能有多个Microsoft Entra ID、Azure AD B2C 或Microsoft个人帐户。

MSAL for Java 通过 IAccount 接口定义了账户这一概念。 这是相较于 ADAL4J 的破坏性变更。 这体现了这样一个事实:同一用户可以拥有多个帐户,这些帐户甚至可能位于不同的 Microsoft Entra 目录中。 MSAL for Java 在来宾场景中能够提供更完善的信息,因为它提供了主帐户信息。

缓存持久性

ADAL4J 不支持令牌缓存。 MSAL for Java添加了令牌缓存,以便尽可能自动刷新过期的令牌,并防止用户提供凭据的不必要的提示,从而简化令牌生存期的管理。

通用机构

在 v1.0 中,如果您使用 https://login.microsoftonline.com/common 授权机构,用户可以使用来自任何组织的 Microsoft Entra 帐户登录。

如果你在 v2.0 中使用 https://login.microsoftonline.com/common 颁发机构,用户可以登录任何 Microsoft Entra 组织,甚至 Microsoft 个人帐户 (MSA)。 在 MSAL for Java 中,如果你想将登录限制在任何 Microsoft Entra 帐户,请使用 https://login.microsoftonline.com/organizations 颁发机构(这与 ADAL4J 的行为相同)。 若要指定颁发机构,请在实例化authority类时在PublicClientApplication.Builder方法中设置PublicClientApplication参数。

v1.0 和 v2.0 令牌

v1.0 端点(由 ADAL 使用)仅颁发 v1.0 令牌。

v2.0 终结点(由 MSAL 使用)可以颁发 v1.0 和 v2.0 令牌。 Web API 的应用程序清单的属性使开发人员能够选择接受哪个版本的令牌。 请参阅accessTokenAcceptedVersion应用程序清单参考文档中的信息。

有关 v1.0 和 v2.0 令牌的详细信息,请参阅Microsoft Entra访问令牌

ADAL 到 MSAL 的迁移

在 ADAL4J 中,刷新令牌已公开,这允许开发人员缓存这些令牌。 然后,他们将使用 AcquireTokenByRefreshToken() 来支持此类解决方案,例如实现长期运行的服务,以便在用户不再处于连接状态时代表用户刷新仪表板。

MSAL for Java不会出于安全原因公开刷新令牌。 而是由 MSAL 代你处理令牌刷新。

MSAL for Java 有一个 API,允许你将使用 ADAL4J 获取的刷新令牌迁移到 ClientApplicationRefreshTokenParameters。 使用此方法可以结合所需的任何范围(资源)提供以前用过的刷新令牌。 刷新令牌将用于换取新的令牌,并将该新令牌缓存起来供您的应用程序使用。

以下代码片段显示了机密客户端应用程序中的简单迁移代码片段:

String rt = GetCachedRefreshTokenForSignedInUser(); // Get refresh token from where you have them stored
Set<String> scopes = Collections.singleton("SCOPE_FOR_REFRESH_TOKEN");

RefreshTokenParameters parameters = RefreshTokenParameters.builder(scopes, rt).build();

PublicClientApplication app = PublicClientApplication.builder(CLIENT_ID) // ClientId for your application
                .authority(AUTHORITY)  //plug in your authority
                .build();

IAuthenticationResult result = app.acquireToken(parameters);

IAuthenticationResult 会返回访问令牌和 ID 令牌,而新的刷新令牌会存储在缓存中。 应用程序现在还将包含一个 IAccount

Set<IAccount> accounts =  app.getAccounts().join();

若要使用缓存中的令牌,请调用:

SilentParameters parameters = SilentParameters.builder(scope, accounts.iterator().next()).build();
IAuthenticationResult result = app.acquireToken(parameters);