向多个后端服务验证 Azure AD 用户

Authenticate Azure AD User to multiple backend services

我正在尝试寻找一种策略来授权 Web 客户端对 Azure 中托管的两个服务进行 HTTP 调用。 Web 客户端都是客户端,两个 API 服务是托管在 Azure 中的 Azure Functions。

对于上述三个应用程序中的每一个,我都在 Azure AD 中设置了应用程序注册,并将两个 Azure Functions 应用程序的范围公开给 Web 客户端,以允许客户端调用它们。我还为两个 API 应用程序设置了应用程序角色,并将这些角色分配给用户。

当 Web 客户端对每个 API 服务进行一次调用时,当前设置运行良好。但是,我希望 Web 客户端调用服务 A,然后服务 A 使用 Web 客户端用户的凭据对服务 B 进行 HTTP 调用。据我所知,当 Web 客户端调用服务 A 时,给 Web 客户端的令牌只有服务 A 的范围和角色,而没有服务 B 的内容。

我的问题是,允许将用户凭据传递到内部服务的推荐策略是什么?特别是当原始令牌没有额外服务的凭据时。

我确实找到了这个问题 (),这与我想要完成的问题非常接近。标记的答案似乎暗示我自己的应用程序负责为额外服务生成新令牌,但我不确定哪个应用程序对此负责。是否建议Web客户端单独向服务B请求获取令牌,并在向服务A的HTTP请求中,在调用时将向服务B的令牌包含在请求正文中?

我 运行 不久前遇到了这样的场景,我必须从前端为后端 API 的用户获取令牌,然后调用 Azure 管理 API在 API 调用的后端。

我最终实施的解决方案是启用令牌获取以调用下游 API,然后使用现有用户的令牌在后端 API 获取令牌。

我的代码 Startup.cs class:

services
    .AddMicrosoftIdentityWebApiAuthentication(Configuration, "ApiSettings")
    .EnableTokenAcquisitionToCallDownstreamApi()//This does the magic
    .AddInMemoryTokenCaches();

在我的 API 控制器中,我不得不使用类似的东西注入 ITokenAcquisition

private readonly ITokenAcquisition _tokenAcquisition;

public MyController(ITokenAcquisition tokenAcquisition)
{
    _tokenAcquisition = tokenAcquisition;
}

然后使用它获取 Azure 管理的令牌 API:

/// <summary>
/// Gets the access token on behalf of signed-in user to perform Azure
/// Resource Manager (ARM) API.
/// </summary>
/// <returns>
/// Access token.
/// </returns>
private async Task<string> GetAccessTokenForAzureSubscriptionManagementApiRequest()
{
    IEnumerable<string> azureServiceManagementApiScopes = <scopes for Azure Management;
    string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(azureServiceManagementApiScopes);
    return accessToken;
}

您可以在此处了解更多信息:https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-web-app-call-api-app-configuration?tabs=aspnetcore

我在阅读了 Microsoft 的这份指南后找到了策略:https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow

一般的想法是让中间层应用程序(服务 A)向 Azure AD 发出 HTTP 请求以获取用户的新令牌。这个新令牌具有针对服务 B 进行身份验证的适当范围和角色,并且包含在对服务 B(针对该用户)的 HTTP 请求中。

根据文档,我选择使用“客户端密码”路由。使用以下 application/x-www-form-urlencoded 内容类型字段向 https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token 发送请求:

我还必须执行 2 个额外步骤来设置我的应用程序。在 Azure 门户中,我转到了服务 A 的应用程序注册,然后:

  1. 在 API 权限下 -> 授予它对服务 B 范围的权限
  2. 在证书和机密下 -> 添加了一个新的客户端机密。这是 HTTP 请求中发送的 client_secret 字段。

另一个答案有这样的例子,但它是针对 ASP.NET 应用程序,而不是 Azure Functions。