您如何从 Azure Active Directory 获取脚手架天气预报 Api 将接受的访问令牌?
How do you get an Access Token from Azure Active Directory that the scaffolded Weather Forecast Api will accept?
我正在尝试构建一个新的 WebApi 使用来自 Azure Active Directory 的访问令牌进行保护。
我正在使用 .net core v3.1 和 visual studio 2019。
我使用“Asp.net 核心 Web 应用程序”模板创建了一个新项目并选择了一个“API”项目并将身份验证类型更改为“工作或学校帐户”并设置应用程序ID Url 到 Api://Automation/TestApi
Visual Studio 然后为我构建了一个带有模拟天气预报服务的网络 API,如果我注释掉 [Authorize] 属性,它会按预期在浏览器中很好地旋转。它还在 AzureActive Directory 中为我创建了一个应用程序注册。
恢复 [Authorize] 属性后,我无法从客户端应用程序调用 API,因此我决定使用邮递员调用 API 以查看发生了什么。
我在创建的应用程序注册 visual studio 中添加了一个客户端密码,并使用应用程序(客户端)ID 和 api://Automation/TestApi/ 将邮递员请求放在一起,如下所示。默认为范围。
这工作正常并且 returns 一个访问令牌但是当我尝试使用该访问令牌调用默认的 weatherforcast 端点时,我在 WWW-Authenticate 响应中收到 HTTP 401 未授权错误和以下内容header
"承载错误="invalid_token", error_description="观众'api://Automation/TestApi'无效"
有什么我想念的吗?我找不到任何关于观众期望的线索,也没有明显的控制方法。
此处应要求公开API屏幕的内容
以及我正在使用的解码后的 jwt 令牌
更新
我尝试了下面@CarlZhao 的回答,但它并没有真正奏效。但是我记得
现在我得到一个以 clientId guid 作为受众的 v2 函数
但是,使用这个token还是不行!!我现在收到有关发行人的错误消息:
Bearer error="invalid_token", error_description="The issuer 'https://login.microsoftonline.com/{{guid}}/v2.0' is invalid
您错过了一些重要的步骤,您的访问令牌也有误,缺少必要的权限。你可以试试我的方法:
您需要创建2个应用程序,一个代表客户端应用程序,另一个代表api应用程序,然后使用客户端应用程序调用Web api应用程序。
首先需要暴露代表web的应用apiapi,可以按照以下流程进行配置:
Azure 门户>应用程序注册>公开 API>添加范围>添加客户端应用程序
因为您使用的是客户端凭证流,接下来,您需要定义api应用程序的清单和为你的客户端应用程序授予应用程序权限(这是你自己定义的角色权限,你可以在添加权限时在我的APIs中找到)。然后你需要点击admin consent 按钮授予管理员同意此权限。
这是为客户端应用程序授予权限:
最后,您可以为您的 api 申请请求令牌:
解析令牌,您将看到:
我取得了一些进一步的进展,我将使用这些进展来提供我自己的答案。
生成的代码使用 Microsoft.AspNetCore.Authentication.AzureAD.UI 包 v 3。1.x 来验证令牌。
使用 Fiddler 我能够看到它使用的是旧端点而不是当前的“V2.0”端点。
这一点的意义在于令牌版本决定了令牌中返回的受众和发行者。
在 V1 令牌中,受众是应用程序注册中的“应用程序 ID Url”,发行者是“https://sts.windows.net/{tennantId}”
在 v2 令牌中,受众是应用程序注册的客户端 ID (GUID),发行者是 https://login.microsoftonline.com/{tenantId}/V2.0。
潜在的问题是这个库期待某种具有 v2.0 令牌受众值(例如客户端 ID)但来自 v1 发行者的混合令牌 https://sts.windows.net/.
我找不到让它查看 v2.0 端点以进行配置的方法,但我在 git 集线器上发现了一个 number of old issues,它有类似的问题,但没有解决就关闭了。
特别是
我的解决方法是在应用程序注册的应用程序注册“清单”json 中设置“accessTokenAcceptedVersion”:2。这可确保令牌中包含正确的受众。
第二步是在启动class的ConfigureServices方法中添加自定义颁发者验证。这是我的代码
AzureADOptions opt = new AzureADOptions();
Configuration.Bind("AzureAd", opt);
string expectedIssuer = $"{opt.Instance}{opt.TenantId}/v2.0";
services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
{
options.TokenValidationParameters.IssuerValidator = (issuer, securityToken, validationParameters) =>
{
if (issuer == expectedIssuer) return issuer;
throw new SecurityTokenInvalidIssuerException("Invalid Issuer")
{
InvalidIssuer = issuer
};
};
});
这确实感觉我正在扫除地毯下存在错误 and/or 配置错误的中间件的潜在问题,我忍不住想一定有更简单的东西 - 这是向导生成的起始代码 visual studio毕竟2019.
我找到了更好的方法,所以我想 post 这个答案可以替代我的第一个答案。
我发现这非常好 sample application and tutorial 并完成了第一部分“桌面应用程序调用 Web Api”并生成了一个 api 使用正确的端点和句柄验证令牌在一个更可预测的庄园。如果你在一个新的网站上陈述 API 我建议使用这个作为起点而不是 visual studio 脚手架的 api。
获取脚手架天气预报api接受令牌访问令牌
- 您需要为客户端和 api 以及@Carl Zhao 和上面链接的教程所建议的范围单独注册应用程序。
- 将 Microsoft.AspNetCore.Authentication.AzureAD.UI nuget 包替换为 Microsoft.Identity.Web
- 在配置服务的 startup.cs 中,将对 services.AddAuthentication(...).AddAzureAdBearer(....) 的调用替换为对 AddMicrosoftIdentityWebApiAuthentication[= 的调用27=]
- 删除 Microsoft.AspNetCore.Authentication.* 的 using 指令并添加 using Microsoft.Identity.Web;
这是我的配置服务现在的样子
public void ConfigureServices(IServiceCollection services)
{
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
services.AddControllers();
}
我的其他答案中出现的自定义发行者验证器不是必需的,可以删除。