Azure active directory AAD API访问委托权限如何工作?

Azure active directory AAD API访问委托权限如何工作?,azure-active-directory,asp.net-core-webapi,azureportal,Azure Active Directory,Asp.net Core Webapi,Azureportal,我在了解API访问代理权限如何与azure active directory一起工作时遇到了一些问题。我觉得我可能误解了AAD工作原理的一个关键方面 这是我的设置 我有一个Web应用程序,我们称之为WebApp。我创造了 Web应用程序的AAD,并使用AAD应用程序ID注册。让我们 称之为应用程序ID A 我有一个Web Api,我们称之为ApiService。我还为它创建了一个AAD,并注册了一个AAD应用程序ID。让我们看看所有的it应用程序ID B 在AAD应用程序ID A中,我已更新了单

我在了解API访问代理权限如何与azure active directory一起工作时遇到了一些问题。我觉得我可能误解了AAD工作原理的一个关键方面

这是我的设置

  • 我有一个Web应用程序,我们称之为WebApp。我创造了 Web应用程序的AAD,并使用AAD应用程序ID注册。让我们 称之为应用程序ID A
  • 我有一个Web Api,我们称之为ApiService。我还为它创建了一个AAD,并注册了一个AAD应用程序ID。让我们看看所有的it应用程序ID B
  • 在AAD应用程序ID A中,我已更新了单击的API访问-> 所需权限->添加(应用程序ID B;Web API)权限
  • 我已经在AAD应用程序ID B中更新了manaifest,以同意 knownClientApplications以包括Web应用程序的客户端ID
  • 我还为两个应用程序启用了oauth2AllowImplicitFlow 舱单
  • 我想做的是,一个用户登录到web应用程序中。当它登录时,用户能够获取特定Web应用程序ID a的令牌。用户应该能够使用该令牌并使用应用程序ID B访问Api服务。我认为,通过在Web应用程序中配置整个Api访问->所需权限,我将获得登录用户与Api通信的委派权限服务WebApi

    当我检查JWT令牌时,我注意到有对MicrosoftGraph的声明,但没有对ApiService的声明。我不应该看到索赔吗

    当我尝试使用该令牌时,它会出现404身份验证错误

    感谢您的建议, 谢谢 德里克

    更新 回应@joonasw

    事实上,我看过了你在我开始时写的例子

    在本例中,web应用程序初始化为:

    .AddOpenIdConnect(opts =>
            {
            Configuration.GetSection("OpenIdConnect").Bind(opts);
                opts.Events = new OpenIdConnectEvents
            {
                OnAuthorizationCodeReceived = ctx =>
                {
                    return Task.CompletedTask;
                }
            };
            });
    
    在HomeController中,有用于检索graph 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;
    }
    
    它将重定向到身份验证页面,然后点击AddOpenIdConnect()方法。但是,openIdConnect配置了web应用clientID/ClientSecret/Resource,因此无法正确存储新令牌。它将再次尝试调用GetAccessTokenAsync(),整个过程将进入无限循环

    在本例中,如果您要注释掉app.settings中的“antentication:resource”,您将在无限循环中遇到同样的问题。发生的情况是,您最初在没有指定资源的情况下正确地进行了身份验证。然后,当您单击尝试获取新资源microsoft graph的令牌时,它在缓存中找不到该令牌,然后尝试一次又一次地重新验证

    我还注意到acquireAsyncAuthentication只返回带有承载令牌类型的AuthenticationResult。在这种情况下,如何获取刷新令牌

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

    更新(解决方案)
    多亏了@jaanus。您所要做的就是将资源更新为web api的clientid,并将其传递到AcquireTokenSilentAsync。您可以从azure门户获取的web api id uri无效

    好吧,看来这里有很多问题。我会尽量让你明白这件事

    将“Web App”的客户端id添加到“ApiService”knownClientApplications是一个好主意。 它允许同时对两个应用程序进行许可。不过,这实际上只适用于多租户场景

    现在,您的Web应用程序将在某个时候获取访问令牌。 当它这样做时,它必须指定一个
    资源
    参数。 此参数告诉AAD您希望调用哪个API。 对于“ApiService”,您应该使用它的客户机id或应用程序id URI(这更常见)

    根据Web应用程序的类型,访问令牌的获取方式略有不同。 对于“传统”后端应用程序,通常使用授权码授权流。 在这个流程中,在用户登录后,您的后端将获得一个授权代码,然后您的Web应用程序可以将该代码交换为访问令牌

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

    出现身份验证错误的原因是,访问令牌可能是针对Microsoft Graph API的。您需要为API请求访问令牌。
    访问令牌始终仅对一个API有效。

    感谢您的回复。我已经用更多的细节更新了我的帖子。问题是,当我指定资源时,我会得到一个无限循环,这可能是我设置的结果。我的设置基于您提供的示例,该示例非常有用,但我认为我缺少一个方面,即在处理两个不同的应用程序ID时,如何配置openId以及如何将其存储在分布式缓存中。”这一方面允许您直接从授权端点(/oauth2/authorize)获取访问令牌不必像通常那样与令牌端点交谈。“难道你不必将Web API AAD端点标记为本机与Web API来实现这一点吗?因此,在OnAuthorizationCodeReceived中,你必须做的是将代码交换为令牌。您可以对两种不同的资源使用它两次。然后,ADAL将使用其令牌缓存缓存令牌。在我的示例中,它由分布式缓存支持。然后,您可以使用AcquireTokenSilent从缓存中获取令牌。由于AAD在您交换代码时也会提供刷新令牌,因此如果需要,ADAL将自动刷新令牌。隐式流用于单页应用程序,可以通过man在任一类型上启用
    context.Result = new ChallengeResult();