我正在维护一个 ASP.NET Core Web API 项目,该项目使用 Duende Identity Server 和 Jwt 不记名令牌,以及对端点的基于角色的访问。
将项目移至.NET 8(将
Microsoft.AspNetCore.App
框架升级到版本8.0.7)后,我开始收到http 403错误。
这是我在
builder.ConfigureServices()
中设置的身份:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer("Bearer", options =>
{
options.Authority = "id.YouDontNeedToKnow.example.com";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false,
NameClaimType = "sub",
RoleClaimType = "role",
ValidTypes = [ "at+jwt" ]
};
});
builder.Services
.AddAuthorization(options =>
{
options.AddPolicy("Admin",
AuthorisationPolicies.Admin());
});
跟踪 Swagger 的端点命中,我发现以下失败:
RolesAuthorizationRequirement:User.IsInRole 对于以下角色之一必须为 true:(管理员)
它从我的 Jwt 读取角色的方式有问题。
此公告描述了我遇到问题的原因。 Asp.Net Core v8 中的重大更改将 TokenValidatedContext.SecurityToken 的默认实际实现从 JwtSecurityToken 更改为 JsonWebToken。
这样做的一个影响是,使用
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear()
来阻止入站声明类型映射 不再有效。
我有一个类型为“角色”的声明,该声明用于包含与我的问题中包含的代码中列出的授权策略相匹配的数据。该声明仍然存在于站点发送的 Bearer 令牌中,但在与 Asp.Net Core 中间件联系时,它会更改为具有
ClaimTypes.Role
标准值的声明:“http://schemas.microsoft.com/ ws/2008/06/身份/声明/角色”。
此时我决定随风而弯,并移除线:
RoleClaimType = "role",
...因为它导致不匹配,所以现在我使用标准声明类型来识别角色声明。删除该行可以解决问题并标准化我的实施。