【问题标题】:How does AAD API Access delegate permission work?AAD API 访问委托权限如何工作?
【发布时间】:2018-07-29 06:26:18
【问题描述】:

我在了解 API 访问委托权限如何与 Azure Active Directory 配合使用时遇到了一些麻烦。我觉得我可能误解了 AAD 工作原理的一个关键方面。

这是我的设置

  1. 我有一个 Web 应用程序,我们称之为 WebApp。我创造了 Web 应用程序的 AAD 并使用 AAD 应用程序 ID 注册。让我们 称之为 App ID A
  2. 我有一个 Web Api,我们称之为 ApiService。我还为它创建了一个 AAD 并使用 AAD App ID 注册。让我们全部使用 App ID B。
  3. 在 AAD App ID A 中,我更新了点击的 API Access -> 所需权限 -> 添加(App ID B ; Web API)权限
  4. 我已更新 AAD 应用程序 ID B 中的清单,以同意 knownClientApplications 以包含 Web 应用的客户端 ID
  5. 我还为两个应用程序启用了 oauth2AllowImplicitFlow 清单。

我正在尝试做的是,用户登录到 Web 应用程序标志。当它登录时,用户能够获取特定 Web App App ID A 的令牌。用户应该能够使用该令牌并使用 App ID B 访问 Api 服务。我想通过配置整个 API 访问-> 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 中它将调用尝试重新验证

context.Result = new ChallengeResult();

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

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

我还注意到,acquireAsyncAuthentication 只返回一个带有不记名令牌类型的 AuthenticationResult。在这种情况下,您将如何获得刷新令牌?

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

更新(解决方案)

感谢@jaanus。您所要做的就是将资源更新为 web api 的 clientid 并将其传递给 AcquireTokenSilentAsync。您可以从 azure 门户获取的 web api id uri 不起作用。

【问题讨论】:

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


    【解决方案1】:

    好的,看来这里有多个问题。我会试着让你理解这些东西。

    将“Web App”的客户端 ID 添加到“ApiService” knownClientApplications 是一个好主意。 它允许同时对两个应用程序进行同意。不过,这真的只对多租户场景很重要。

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

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

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

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

    【讨论】:

    • 感谢您的回复。我已经用更多细节更新了我的帖子。问题是当我指定资源时,我得到一个无限循环,这可能是我的设置的结果。我的设置基于您提出的示例,这确实很有帮助,但我认为我缺少关于如何配置 openId 以及在处理两个不同的应用程序 ID 时如何将其存储在分布式缓存中的一个方面。
    • “这个允许您直接从授权端点 (/oauth2/authorize) 获取访问令牌,而无需像往常那样与令牌端点对话。”您不必将 Web API AAD 端点标记为原生与 Web api 来实现这一点吗?
    • 所以你必须在 OnAuthorizationCodeReceived 中做的是用代码交换令牌。您可以将它两次用于两种不同的资源。然后 ADAL 将使用其令牌缓存来缓存令牌。在我的示例中,它由分布式缓存支持。然后稍后您可以使用 AcquireTokenSilent 从缓存中获取令牌。由于 AAD 在您交换代码时也会提供刷新令牌,因此 ADAL 会在需要时自动刷新令牌。
    • 隐式流适用于单页应用程序,可以通过清单在任一类型上启用。虽然基本上单页应用程序应该被标记为原生,因为它们在用户设备上运行。
    • 哦,记住,在Web App端交换token时,必须使用Web App的client id和secret,并使用API​​的client id/app id URI作为资源。
    猜你喜欢
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    相关资源
    最近更新 更多