代码之家  ›  专栏  ›  技术社区  ›  FIL

TokenCache是否应用于MSAL的脱机访问?

  •  1
  • FIL  · 技术社区  · 7 年前

    我正在使用MSAL实现身份验证,我需要一些处理刷新令牌的指导。

    我的Angular Web应用正在使用我的ASP进行身份验证。NET Web API使用MSAL。Web API需要一些作用域来访问Microsoft Graph,因此它使用 "On Behalf Of" OAuth 2.0 flow 获取用于调用MS Graph的访问令牌。这一部分已经完成,并且有效。

    问题是,一段时间后,我的用户将调用MS Graph。NET守护程序应用程序(使用OBO流)访问令牌到期时。

    我需要的是通过我的Web API获取刷新令牌,并将其缓存(例如,在SQL数据库中),以便守护程序应用程序可以读取该令牌,并用于获取有效的访问令牌。

    我想 TokenCache 对于机密客户端应用程序来说,这是正确的方法,但我不确定如何通过daemon应用程序获得有效的访问令牌。

    下面是我想用来从AAD获取访问令牌的守护程序应用程序的代码:

    var userAssertion = new UserAssertion(
        <accessToken>,
        "urn:ietf:params:oauth:grant-type:jwt-bearer");
    var authority = authEndpoint.TrimEnd('/') + "/" + <tenant> + "/";
    var clientCredencial = new ClientCredential(<clientSecret>);
    var authClient = new ConfidentialClientApplication(<clientId>, authority, <redirectUri>, 
        clientCredencial, <userTokenCache>, null);
    
    try
    {
        var authResult =
            await authClient.AcquireTokenOnBehalfOfAsync(<scopes>, userAssertion, authority);
        activeAccessToken = authResult.AccessToken;
    }
    catch (MsalException ex)
    {
        throw;
    }
    

    我应该提供吗 <userTokenCache> 获取刷新令牌表单缓存?如果是, UserAssertion 需要一个 <accessToken> 但我不知道应该使用什么价值。

    还是我应该做一个 token request 因为MSAL不支持刷新令牌,所以我可以自己从响应中获取刷新令牌吗?然后我可以将刷新令牌存储在数据库中,并将其用作 <accessToken> 具有 null 像 <userTokenCache> 在daemon应用程序中。

    我以为可以使用MSAL获取刷新令牌,但我发现 it is not .

    使现代化

    我忘了说我所有的应用程序都使用相同的应用程序ID(这是由于AADv2端点的限制,尽管我刚刚发现了这一点) it was removed from the docs at Nov 2nd 2018 ).

    为什么不让客户端凭据流动?

    与MS Graph的通信可以在Web API中执行(使用OBO流),但任务可能会被用户延迟,例如8小时后发送邮件(Web API将任务存储在数据库中)。这种情况的解决方案是一个应用程序(守护进程),它按计划运行,从数据库获取任务,并执行对MS Graph的调用。我不想让管理员同意我的任何应用,因为 获得用户的同意非常重要 .如果同意被撤销,则不应致电MS Graph。这就是为什么守护程序应用程序应该使用刷新令牌从AAD获取访问令牌以访问MS Graph(使用OBO流)。

    我希望现在一切都清楚了。也许我不应该这样做。如有任何建议,将不胜感激。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Jean-Marc Prieur    7 年前

    MSAL本身处理刷新令牌,您只需要处理缓存序列化。-这个 userTokenCache 由OBO调用使用,您可以通过首先调用AcquireTokenSilentAsyn来使用刷新令牌(这就是刷新令牌的方式) -客户端凭据流(AcquireTokenForApplication)使用applicationTokenCache。

    我建议你看一下下面的例子,它说明了海外建筑运营管理局: https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2 尤其是 TodoListService/Extensions/TokenAcquisition.cs#L275-L294

    代码是:

    var accounts = await application.GetAccountsAsync();
    try
    {
     AuthenticationResult result = null;
     var allAccounts = await application.GetAccountsAsync();
     IAccount account = await application.GetAccountAsync(accountIdentifier);
     result = await application.AcquireTokenSilentAsync(scopes.Except(scopesRequestedByMsalNet), account);
     return result.AccessToken;
    }
    catch (MsalUiRequiredException ex)
    {
     ...
    

    现在,缓存本身已从客户端发送到Web API的承载令牌初始化。看见

    TodoListService/Extensions/TokenAcquisition.cs#L305-L336

    private void AddAccountToCacheFromJwt(IEnumerable<string> scopes, JwtSecurityToken jwtToken, AuthenticationProperties properties, ClaimsPrincipal principal, HttpContext httpContext)
    {
     try
     {
      UserAssertion userAssertion;
      IEnumerable<string> requestedScopes;
      if (jwtToken != null)
      {
       userAssertion = new UserAssertion(jwtToken.RawData, "urn:ietf:params:oauth:grant-type:jwt-bearer");
       requestedScopes = scopes ?? jwtToken.Audiences.Select(a => $"{a}/.default");
      }
      else
      {
       throw new ArgumentOutOfRangeException("tokenValidationContext.SecurityToken should be a JWT Token");
       }
    
       var application = CreateApplication(httpContext, principal, properties, null);
    
       // Synchronous call to make sure that the cache is filled-in before the controller tries to get access tokens
       AuthenticationResult result = application.AcquireTokenOnBehalfOfAsync(scopes.Except(scopesRequestedByMsalNet), userAssertion).GetAwaiter().GetResult();
      }
      catch (MsalUiRequiredException ex)
      {
       ...
    
    推荐文章