调用 Web API 的 Web API:代码配置

本文介绍了如何使用 OAuth 2.0 授权代码流为 Web API 应用配置代码。

Microsoft 建议在调用下游 Web API 开发 ASP.NET Core 保护的 API 时,使用 Microsoft.Identity.Web NuGet 包。 请参阅受保护的 Web API:代码配置 | Microsoft.Identity.Web,在 Web API 的上下文中快速了解该库。

先决条件

配置应用

为 Web API 选择语言。

客户端密码或客户端证书

鉴于 Web 应用现在调用下游的 Web API,请提供 appsettings.json 文件中客户端密码或客户端证书。 你还可以添加一个节来指定:

  • 下游 Web API 的 URL
  • 调用 API 所需的范围

在下面的示例中,GraphBeta 节指定了这些设置。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "[Enter_the_Application_Id_Here]",
    "TenantId": "common",

   // To call an API
   "ClientCredentials": [
    {
      "SourceType": "ClientSecret",
      "ClientSecret":"[Enter_the_Client_Secret_Here]"
    }
  ]
 },
 "GraphBeta": {
    "BaseUrl": "https://graph.microsoft.com/beta",
    "Scopes": ["user.read"]
    }
}

注意

你可建议一组客户端凭据,其中包括无凭据解决方案,例如 Azure Kubernetes 的工作负载联合身份验证。 先前版本的 Microsoft.Identity.Web 在单个属性“ClientSecret”中(而非“ClientCredentials”中)表示客户端密码。 这仍然支持向后兼容,但你不能同时使用“ClientSecret”属性和“ClientCredentials”集合。

你可以提供客户端证书,而不是客户端密码。 以下代码片段演示如何使用存储在 Azure Key Vault 中的证书。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "[Enter_the_Application_Id_Here]",
    "TenantId": "common",

   // To call an API
   "ClientCredentials": [
      {
        "SourceType": "KeyVault",
        "KeyVaultUrl": "https://msidentitywebsamples.vault.azure.net",
        "KeyVaultCertificateName": "MicrosoftIdentitySamplesCert"
      }
   ]
  },
  "GraphBeta": {
    "BaseUrl": "https://graph.microsoft.com/beta",
    "Scopes": ["user.read"]
  }
}

警告

如果忘记将 Scopes 更改为数组,则当尝试使用 IDownstreamApi 时,范围会显示为 null,并且 IDownstreamApi 会尝试匿名(未经身份验证)调用下游 API,这会导致 401/unauthenticated

Microsoft.Identity.Web 提供了多种通过配置或代码描述证书的方法。 有关详细信息,请参阅 GitHub 上的 Microsoft.Identity.Web - 使用证书

Program.cs

using Microsoft.Identity.Web;

// ...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration, Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();
// ...

Web API 需要获取下游 API 的令牌。 通过在 .AddMicrosoftIdentityWebApi(Configuration) 后面添加 .EnableTokenAcquisitionToCallDownstreamApi() 行来指定它。 此行公开可在控制器/页面操作中使用的 ITokenAcquisition 服务。

但是,一种替代方法是实现令牌缓存。 例如,将 .AddInMemoryTokenCaches() 添加到 Program.cs 可将令牌缓存在内存中。

using Microsoft.Identity.Web;

// ...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration, Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();
// ...

Microsoft.Identity.Web 提供了用于从另一个 API 调用某个下游 Web API 的两种机制。 选择哪种方式取决于你是要调用 Microsoft Graph 还是调用另一个 API。

选项 1:调用 Microsoft Graph

若要调用 Microsoft Graph,可通过 Microsoft.Identity.Web 在 API 操作中直接使用 GraphServiceClient(由 Microsoft Graph SDK 公开)。

注意

Microsoft Graph SDK v5+ 存在一个持续的问题。 有关详细信息,请参阅 GitHub 问题

若要公开 Microsoft Graph:

  1. Microsoft.Identity.Web.GraphServiceClient NuGet 包添加到项目。
  2. 在 Program.cs 中的 .EnableTokenAcquisitionToCallDownstreamApi() 后面添加 .AddMicrosoftGraph().AddMicrosoftGraph() 具有多个重写。 使用将配置部分作为参数的重写,代码变为:
using Microsoft.Identity.Web;

// ...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration, Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddMicrosoftGraph(Configuration.GetSection("GraphBeta"))
    .AddInMemoryTokenCaches();
// ...

选项 2:调用下游 Web API,而不是 Microsoft Graph

  1. Microsoft.Identity.Web.DownstreamApi NuGet 包添加到项目。
  2. 在 Program.cs 中的 .EnableTokenAcquisitionToCallDownstreamApi() 后面添加 .AddDownstreamApi()。 代码变为:
using Microsoft.Identity.Web;

// ...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration, "AzureAd")
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDownstreamApi("MyApi", Configuration.GetSection("MyApiScope"))
    .AddInMemoryTokenCaches();
// ...

where;

  • MyApi 表示你的 Web API 要调用的下游 Web API 的名称
  • MyApiScope 是你的 Web API 为了与下游 Web API 交互所需请求的范围

这些值将在 JSON 中表示,将类似于以下代码片段。

"DownstreamAPI": {
      "BaseUrl": "https://downstreamapi.contoso.com/",
      "Scopes": "user.read"
    },

如果 Web 应用需要调用另一个 API 资源,请基于相关范围重复 .AddDownstreamApi() 方法,如以下代码片段所示:

using Microsoft.Identity.Web;

// ...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration, "AzureAd")
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDownstreamApi("MyApi", Configuration.GetSection("MyApiScope"))
    .AddDownstreamApi("MyApi2", Configuration.GetSection("MyApi2Scope"))
    .AddInMemoryTokenCaches();
// ...

请注意,在没有任何参数的情况下调用 .EnableTokenAcquisitionToCallDownstreamApi,这意味着在控制器通过指定范围来请求令牌时即时获取访问令牌。

你还可以在调用 .EnableTokenAcquisitionToCallDownstreamApi 时传入范围,这将使 Web 应用在初始用户登录过程中获取令牌。 然后,当控制器请求令牌时,将从缓存中拉取该令牌。

与 Web 应用类似,可以选择各种令牌缓存实现。 有关详细信息,请参阅 GitHub 上的 Microsoft 标识 Web - 令牌缓存序列化

下图显示了 Microsoft.Identity.Web 的可能性及其对 Program.cs 的影响:

此框图显示了 Startup.cs 中的服务配置选项,用于调用 Web API 和指定令牌缓存实现

注意

若要完全理解以下代码示例,请熟悉 ASP.NET Core 基础知识,尤其是依赖项注入选项

也可以参阅 Node.js 和 Azure Functions 中的 OBO 流实现示例。

协议

有关 OBO 协议的详细信息,请参阅 Microsoft 标识平台和 OAuth 2.0 代理流

下一步