调用 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.partner.microsoftonline.cn/",
"ClientId": "[Enter_the_Application_Id_Here]",
"TenantId": "common",
// To call an API
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret":"[Enter_the_Client_Secret_Here]"
}
]
},
"GraphBeta": {
"BaseUrl": "https://microsoftgraph.chinacloudapi.cn/beta",
"Scopes": ["https://microsoftgraph.chinacloudapi.cn/user.read"]
}
}
注意
你可建议一组客户端凭据,其中包括无凭据解决方案,例如 Azure Kubernetes 的工作负载联合身份验证。 先前版本的 Microsoft.Identity.Web 在单个属性“ClientSecret”中(而非“ClientCredentials”中)表示客户端密码。 这仍然支持向后兼容,但你不能同时使用“ClientSecret”属性和“ClientCredentials”集合。
你可以提供客户端证书,而不是客户端密码。 以下代码片段演示如何使用存储在 Azure Key Vault 中的证书。
{
"AzureAd": {
"Instance": "https://login.partner.microsoftonline.cn/",
"ClientId": "[Enter_the_Application_Id_Here]",
"TenantId": "common",
// To call an API
"ClientCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://msidentitywebsamples.vault.azure.cn",
"KeyVaultCertificateName": "MicrosoftIdentitySamplesCert"
}
]
},
"GraphBeta": {
"BaseUrl": "https://microsoftgraph.chinacloudapi.cn/beta",
"Scopes": ["https://microsoftgraph.chinacloudapi.cn/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:
- 将 Microsoft.Identity.Web.GraphServiceClient NuGet 包添加到项目。
- 在 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
- 将 Microsoft.Identity.Web.DownstreamApi NuGet 包添加到项目。
- 在 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": "https://microsoftgraph.chinacloudapi.cn/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 的影响:
注意
若要完全理解以下代码示例,请熟悉 ASP.NET Core 基础知识,尤其是依赖项注入和选项。
也可以参阅 Node.js 和 Azure Functions 中的 OBO 流实现示例。
协议
有关 OBO 协议的详细信息,请参阅 Microsoft 标识平台和 OAuth 2.0 代理流。