【问题标题】:access token / refresh token with MSAL使用 MSAL 访问令牌/刷新令牌
【发布时间】:2018-07-13 20:03:30
【问题描述】:

我对 OAuth2 以及 AccessToken 和 RefreshToken 的概念比较熟悉。

看起来 MSAL 在使用 ClientApplicationBase.AcquireTokenSilentAsync() 时正在为我们做一些工作。

我不清楚它是否会一直检查当前 AccessToken 的过期时间并在方法调用时自动刷新它(使用 RefreshToken)。

无论如何,对于我们应该多久调用一次 AcquireTokenSilentAsync() 是否有“最佳实践”?我们是否应该自己跟踪过期并调用此方法来更新我们的不记名身份验证标头?我们应该在每个请求上调用 AcquireTokenSilentAsync() 吗? (怀疑)

我看不到使用 DelegateAuthenticationProvider 的 GraphServiceClient(我知道的切线主题)将如何做任何有用的 WRT 刷新。当令牌接近到期时,我们是否需要扩展该类并执行我们自己的刷新?我觉得这应该/应该已经在 SDK 中了。

感谢您的任何提示。 -AJ

【问题讨论】:

    标签: msal


    【解决方案1】:

    2020 年 11 月更新

    这个答案最初是为 MSAL 客户端的 V2 编写的。从那时起,已经发布了一个 V3,它的工作方式可能与 V2 不同。

    原答案

    我不清楚它是否会始终检查当前 AccessToken 的过期时间并在方法调用时自动刷新它(使用 RefreshToken)。

    如果我正确理解this answer,则在提供offline_access 范围时会自动提供刷新令牌

    ...您已请求offline_access 范围,因此您的应用会收到刷新令牌。

    AcquireTokenSilentAsyncdescription 表示当提供刷新令牌时,它将检查令牌上的到期日期,如果它已过期或即将到期,则获取一个新的。

    如果访问令牌已过期或即将过期(5 分钟内 窗口),然后刷新令牌(如果可用)用于获取新的 通过网络调用访问令牌。

    它将重复此行为,直到刷新令牌过期。或者,您可以通过 utilizing forceRefresh 参数上的 AcquireTokenSilentAsync 上的 forceRefresh 参数强制刷新访问令牌

    最后,我要引用 this answer on SO,因为它提供了有关 MSAL 和令牌的很好的见解

    只是为了澄清一下,MSAL 实际上并不发行令牌 或决定令牌到期,而是摄取获取令牌 来自 Azure AD STS。

    MSAL 将在过期后自动刷新您的访问令牌 调用 AcquireTokenSilentAsync 时。 .... 默认令牌 现在的到期时间是:

    访问令牌:1 小时

    刷新令牌:90 天,14 天非活动滑动窗口

    (2017 年 6 月 13 日)

    无论如何,对于我们应该多久调用一次,是否有“最佳实践” AcquireTokenSilentAsync() ?我们是否应该跟踪到期 我们自己并调用这个方法来更新我们的承载认证 标题?我们是否应该在每次调用 AcquireTokenSilentAsync() 请求?

    documentation 还列出了用于调用AcquireTokenSilentAsync 的“推荐调用模式”。文档also 提到了

    对于公共客户端和机密客户端应用程序,MSAL.NET 维护一个令牌缓存(或在机密客户端应用程序的情况下为两个缓存),并且应用程序应先尝试从缓存中获取令牌,然后再通过其他任何方式。

    根据我看到的示例,包括文档中推荐的调用模式,我认为您可以简单地调用 AcquireTokenSilentAsync 并捕获 MsalUiRequiredException 作为令牌已过期并且用户必须登录的指示又进来了。

    我看不出使用 DelegateAuthenticationProvider 的 GraphServiceClient(切线主题,我知道)将如何做任何有用的 WRT 刷新。当令牌接近到期时,我们是否需要扩展该类并执行我们自己的刷新?我觉得这应该/应该已经在 SDK 中了。

    如果我正确理解了 DelegateAuthenticationProvider,它所做的就是在我们将 requestMessage 传递给 Graph 之前对其进行修改。我们要做的就是为我们的访问令牌提供请求的授权标头。我们已经知道,当我们获取访问令牌时,它是有效的,所以我们可以添加它。

            new DelegateAuthenticationProvider(async (requestMessage) =>
            {
                ConfidentialClientApplication cca = new ConfidentialClientApplication(_ClientId, _Authority, _RedirectUri, new ClientCredential(_ClientSecret), _UserTokenSessionCache.GetTokenCache(identifier, httpContext), _ApplicationTokenCache.GetTokenCache());
                AuthenticationResult result = await cca.AcquireTokenSilentAsync();
                requestMessage.Headers.Add("Authorization", result.CreateAuthorizationHeader());
                //OR
                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken);
            });
    

    (在设置标题的任何一种方式之间都有no difference

    我一直走这条路,这对我有用。我强烈建议阅读他们的文档,因为它确实为如何实现 MSAL.Net 提供了很好的见解。

    我还没有时间玩弄令牌持续时间。如果没有提供刷新令牌(如果可能的话)也不是行为

    我希望这会有所帮助!

    【讨论】:

    • 所以基本上建议是在进行任何类型的 REST 调用之前调用AcquireTokenAsync()?据我所知,替代方案是发送令牌,无论何时返回 403 并做出反应。或者通过在每次休息调用之前检查代码中的到期日期。
    • 您写道,“AcquireTokenSilentAsync 的描述暗示当提供刷新令牌时,它会检查令牌上的到期日期,如果它已过期或即将到期,则获取一个新的。如果访问令牌已过期或接近过期(在 5 分钟窗口内),然后刷新令牌(如果可用)用于通过网络调用获取新的访问令牌。”那么,如果 refresh 令牌已过期,我们如何配置 MSAL 客户端以通过登录过程发送用户?我收到AADSTS700081: The refresh token has expired due to maximum lifetime...
    • 自从我上次使用 MSAL.NET 已经过去了 2 年多一点,所以这些信息可能已经过时了。但我理解如何处理它的方式是捕获AcquireTokenSilent 引发的MSALUIRequired 异常,如果刷新令牌已过期,并使用AcquireTokenXXX 方法之一来获取一组新的令牌。以为这是我对 V2 的理解,2 年前。不确定它今天是否仍然有效:/
    【解决方案2】:

    提到上面遗漏的一件事,引用我对Get refresh token with Azure AD V2.0 (MSAL) and Asp .Net Core 2.0的回答

    • 对于上下文,OAuth 2.0 code grant flow 提到了以下步骤:
      • 授权,返回auth_code
      • 使用 auth_code,获取 access_token(通常有效期为 1 小时)和 refresh_token
      • access_token 用于获取相关资源的访问权限
      • access_token过期后,使用refresh_token获取新的access_token
    • MSAL.NET 通过 TokenCache 抽象了 refresh_token 的概念。

    希望这能阐明为什么 TokenCache 是 MSAL.NET 中的“新”refresh_token,而 TokenCache 是您需要序列化和保存的。有像 Microsoft.Identity.Client.Extensions.Msal 这样的库可以帮助解决这个问题。

    @AlWeber/@Raziel,以下模式适用于 PublicClientApplication:

    • 在启动时,为了反序列化和加载TokenCache(有refresh_token),尝试静默获取access_token。
    • 如果失败,请使用交互式 UI 获取令牌。
    • 保存并重新使用具有AccessToken 和ExpiresOn 的AuthenticationResult。一旦您接近 ExpiresOn 属性(个人而言,我在到期前 30 分钟设置),重做 access_token 静默获取(如果您是 API 用户,则有点昂贵,因此会缓存结果)。

    对于我们应该多久调用一次 AcquireTokenSilentAsync() 是否有“最佳实践”?我们是否应该自己跟踪到期并调用此方法来更新我们的不记名身份验证标头?我们应该在每个请求上调用 AcquireTokenSilentAsync() 吗? (怀疑)

    我认为这不是一个好主意。如前所述,这个电话仍然有点贵。另一种方法是将 AuthenticationResult 存储在内存中,重新使用它,然后只在 ExpiresOn 属性附近进行静默获取工作流。

    【讨论】:

      猜你喜欢
      • 2019-06-29
      • 2020-07-12
      • 2015-07-19
      • 1970-01-01
      • 2019-01-13
      • 2022-10-31
      • 2020-06-12
      • 1970-01-01
      • 2014-09-13
      相关资源
      最近更新 更多