AAD API访问委派权限如何运作?

时间:2018-02-19 03:08:14

标签: azure-active-directory asp.net-core-webapi azureportal

我在跟踪API访问委派权限如何与azure活动目录一起工作时遇到了一些麻烦。我觉得我可能误解了AAD的工作方式。

这是我的设置

  1. 我有一个Web应用程序,我们称之为WebApp。我创造了 Web应用程序的AAD,并使用AAD App ID注册。让我们 称之为App ID A
  2. 我有一个Web Api让我们称之为ApiService。我还为它创建了一个AAD并注册了AAD App ID。我们就是App ID B。
  3. 在AAD App ID A中,我更新了点击API访问权限 - > 必需的权限 - >添加(App ID B; Web API)权限
  4. 我更新了AAD App ID B中的manaifest,以表示同意 knownClientApplications包含Web App的客户端ID
  5. 我也启用oauth2AllowImplicitFlow对两个App都是真的 清单。
  6. 我要做的是,用户登录Web应用程序标志。当它登录时,用户能够获取特定Web App App ID A的令牌。用户应该能够使用该令牌并访问具有App ID B的Api服务。我想通过配置整个API Access - > Web应用程序中的必需权限,它将授予我与登录用户的委托权限,以便与Api服务WebApi进行通信。

    当我检查JWT令牌时,我注意到有一个Microsoft Graph的声明,但不是ApiService的声明。我不应该看到索赔吗?

    当我尝试使用令牌时,它会对404身份验证错误做出反应。

    任何建议表示赞赏, 谢谢, 德里克

    更新

    回应@joonasw

    我实际上看了你开始时写的例子。

    https://joonasw.net/view/aspnet-core-2-azure-ad-authentication

    在该示例中,Web应用程序初始化为:

    .AddOpenIdConnect(opts =>
            {
            Configuration.GetSection("OpenIdConnect").Bind(opts);
                opts.Events = new OpenIdConnectEvents
            {
                OnAuthorizationCodeReceived = ctx =>
                {
                    return Task.CompletedTask;
                }
            };
            });
    

    在HomeController中,有代码可以检索图形api的标记

    private async Task<string> GetAccessTokenAsync()
    {
        string authority = _authOptions.Authority;
    
        string userId = User.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
        var cache = new AdalDistributedTokenCache(_cache, _dataProtectionProvider, userId);
    
        var authContext = new AuthenticationContext(authority, cache);
    
        //App's credentials may be needed if access tokens need to be refreshed with a refresh token
        string clientId = _authOptions.ClientId;
        string clientSecret = _authOptions.ClientSecret;
        var credential = new ClientCredential(clientId, clientSecret);
    
        var result = await authContext.AcquireTokenSilentAsync(
            "https://graph.microsoft.com",
            credential,
            new UserIdentifier(userId, UserIdentifierType.UniqueId));
    
        return result.AccessToken;
    }
    

    根据我的理解,当用户最初登录到Web应用程序时,它将触发OnAuthorizationCodeReceived()方法,在该方法中它将使用Web应用程序的clientId / clientSecret / resource。令牌存储在密钥资源/客户端ID下的分布式令牌缓存中。

    在示例中,GetAccessTokenAsync()用于获取令牌以访问图API。

    就我而言,我希望更新该方法以检索具有不同clientId / clientSecret / resoruce的WebApi的令牌。在我的情况下,它将AcquireTokenSilentAsync将抛出AdalTokenAcquisitionExceptionFilter,因为所需的令牌不存储在缓存中,而在AdalTokenAcquisitionExceptionFilter中它将调用try to reauthenticate

    context.Result = new ChallengeResult();
    

    将重定向到身份验证页面,然后点击AddOpenIdConnect()方法。但是,openIdConnect配置了Web应用程序clientID / ClientSecret / Resource,并且不会正确存储新令牌。它将尝试再次调用GetAccessTokenAsync(),整个过程将进入无限循环。

    在该示例中,如果您要在app.settings中注释掉“Anthentication:resource”,您将遇到与无限循环相同的问题。会发生什么是您最初在没有指定资源的情况下正确验证。然后,当您单击时,尝试获取微软图形的令牌,这是一种新资源,它无法在缓存中找到它,然后尝试反复重新验证。

    我还注意到acquireAsyncAuthentication仅返回带有bekentype承载的AuthenticationResult。在这种情况下,您将如何获得刷新令牌?

    有什么建议吗? 谢谢, 德里克

    更新(解决方案)

    感谢@jaanus。您所要做的就是将资源更新为web api的clientid并将其传递给AcquireTokenSilentAsync。您可以从天蓝色门户网站获取的Web api id uri无效。

1 个答案:

答案 0 :(得分:2)

好的,所以看来这里有很多问题。我会尝试对你有所了解。

将&#34; Web App&#34;的客户端ID添加到&#34; ApiService&#34; knownClientApplications是个好主意。 它允许同时为两个应用程序同意。这实际上只对多租户场景有用。

现在,您的Web App将在某个时刻获取访问令牌。 如果是,则必须指定resource参数。 此参数向AAD说明您要调用的API。 对于&#34; ApiService&#34;,您应该使用其客户端ID或应用程序ID URI(这是更常见的)。

根据Web App的类型,访问令牌的获取方式略有不同。 对于&#34;传统&#34;后端应用程序,通常使用授权代码授权流程。 在此流程中,您的后端在用户登录后获取授权代码,然后您的Web App可以交换访问令牌的代码。

对于前端JavaScript应用程序,您将使用您允许的隐式授权流程(顺便说一下,无需在API中启用它)。 这个允许您直接从授权端点(/ oauth2 / authorize)访问令牌,而无需像往常那样与令牌端点通信。 如果您愿意,您可以在登录URL片段后立即获取访问令牌。 如果你要走这条路,ADAL.JS会让你更加轻松。

您收到身份验证错误的原因是因为访问令牌可能适用于Microsoft Graph API。您需要为API请求访问令牌。 访问令牌始终仅对一个API有效。