问题描述
我正在尝试构建一个新的WebApi,该WebApi使用来自Azure活动目录的访问令牌来保护。
我正在使用.net core v3.1和Visual Studio 2019。
我使用“ Asp.net核心Web应用程序”模板创建了一个新项目,并选择了“ API”项目,并将身份验证类型更改为“工作或学校帐户”,并将“应用程序ID网址”设置为Api:// Automation / TestApi
然后,Visual Studio用模拟天气预报服务为我提供了一个Web API,如果我注释掉了[Authorize]属性,它可以按预期在浏览器中很好地旋转。它还在AzureActive Directory中为我创建了应用程序注册。
使用[Authorize]属性恢复原位后,我无法从客户端应用程序调用API,因此我决定使用邮递员调用API以查看发生的情况。
我在创建的应用注册Visual Studio中添加了一个客户端机密,并使用Application(客户端)ID和api://Automation/TestApi/.default作为范围将邮递员请求汇总如下。
这可以正常工作并返回访问令牌,但是当我尝试使用该访问令牌来调用默认的Weatherforcast端点时,在WWW-Authenticate响应标头中收到HTTP 401未经授权的错误
“ bearer error =” invalid_token“,error_description =”观众'api:// Automation / TestApi'无效”
有什么我想念的吗?我无法找到有关预期观众是什么的线索,也没有明显的控制方式。
此处要求的是公开API屏幕的内容
和我正在使用的解码的jwt令牌
更新
我在下面尝试了@CarlZhao的答案,但实际上没有用。但是我记得a question I asked a while ago about the wrong issuer in the token的结果是手动编辑API注册中的清单json并设置“ accesstokenAcceptedVersion”:2
现在我获得了以clientId guid为受众的v2函数
但是,使用此令牌仍然无效!我现在收到有关发行人的错误:
Bearer error="invalid_token",error_description="The issuer 'https://login.microsoftonline.com/{{guid}}/v2.0' is invalid
解决方法
您错过了一些重要步骤,您的访问令牌也错了,它缺少必要的权限。您可以尝试遵循我的方法:
您需要创建2个应用程序,一个代表客户端应用程序,另一个代表api应用程序,然后使用该客户端应用程序调用Web api应用程序。
首先,您需要公开代表Web api的应用程序的api,可以按照以下过程进行配置:
Azure门户>应用程序注册>公开API>添加作用域>添加客户端应用程序
因为您使用的是客户端凭据流,接下来,您需要定义api应用程序的清单并向客户端应用程序授予应用程序权限(这是角色您定义自己的权限,您可以在添加权限时在我的API 中找到它。然后,您需要点击管理员同意按钮以授予管理员对此权限的同意。 / p>
This是定义清单的过程。
这是授予客户端应用程序权限:
最后,您可以为您的api应用程序请求令牌:
解析令牌,您将看到:
,我已经取得了一些进一步的进步,将用于提供自己的答案。
生成的代码使用Microsoft.AspNetCore.Authentication.AzureAD.UI软件包v 3.1.x来验证令牌。
使用Fiddler,我可以看到它使用的是较旧的终结点,而不是当前的“ V2.0”终结点。
这样做的意义在于令牌版本规定了令牌中返回的受众和发行者。
在V1令牌中,受众是应用程序注册中的“应用程序ID网址”,发行人是“ 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。这样可以确保令牌中包含正确的受众。
第二步是在启动类的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
};
};
});
这确实感觉像我正在扫除地毯下的错误和/或配置错误的中间件的根本问题,我不禁想到必须有一些更简单的东西-毕竟这是从Visual Studio 2019向导生成的入门代码。
,我找到了一种更好的方法,以为我可以将答案发布为第一个答案的替代方法。
我发现这很好sample application and tutorial,并通过第一部分“ Desktop App Calls Web Api”进行了工作,并生成了一个使用正确端点并进行处理的api,该api以更可预测的方式对令牌进行了验证。如果您要使用新的Web API,我建议您以此为起点,而不是使用Visual Studio支架的api。
要获取支架式天气预报API来接受令牌访问令牌
- 您需要分别为客户端和api进行应用程序注册,以及@Carl Zhao和上面链接的教程建议的范围。
- 用Microsoft.Identity.Web替换Microsoft.AspNetCore.Authentication.AzureAD.UI nuget包
- 在startup.cs中的“配置服务”中,将对services.AddAuthentication(...)。AddAzureAdBearer(....)的调用替换为对AddMicrosoftIdentityWebApiAuthentication的调用
- 删除Microsoft.AspNetCore.Authentication。*的using指令,并使用Microsoft.Identity.Web进行添加;
这是我的配置服务现在的样子
public void ConfigureServices(IServiceCollection services)
{
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
services.AddControllers();
}
我的其他答案中显示的自定义发行人验证器没有要求,可以删除。