ASP.NET Core策略校验缺失aud claim导致授权失败,但id token中存在该声明
问题根本原因
ASP.NET Core 3.1自带的OpenIdConnect中间件默认会对JWT的标准声明做映射转换,aud声明会被自动映射为http://schemas.microsoft.com/identity/claims/audience(对应System.Security.Claims.ClaimTypes.Audience常量),你直接用"aud"作为键名查找声明自然会匹配失败。
你之前设置JwtSecurityTokenHandler.DefaultMapInboundClaims = false不生效,大概率是把这段代码放在了AddAuthentication/AddOpenIdConnect配置之后,中间件已经初始化完成,配置没有生效。
可选解决方案
方案1:直接使用映射后的声明类型(改造成本最低)
直接用微软官方定义的ClaimTypes.Audience常量作为声明键写授权策略即可:
using System.Security.Claims; // Configure your policies services.AddAuthorization(options => options.AddPolicy("Registered", policy => policy.RequireClaim(ClaimTypes.Audience, Configuration["SampleApp:ClientId"])));
方案2:保留aud短声明名的使用习惯
首先要把关闭声明映射的代码挪到ConfigureServices方法的最开头,在所有认证相关配置之前执行:
// 必须放在AddAuthentication调用之前才会生效 JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
然后在OpenIdConnect配置中指定声明匹配规则:
services.AddAuthentication(options => { // 保留你原有的认证配置 }) .AddOpenIdConnect(options => { // 保留你原有的其他OIDC配置 options.TokenValidationParameters = new TokenValidationParameters { // 保留你原有的校验配置(如ValidateIssuer、ValidateAudience等) NameClaimType = "sub", RoleClaimType = "role" }; });
配置完成后你原本用"aud"作为键的授权策略就可以正常生效。
方案3:手动补全声明(临时调试用)
如果你不确定当前声明的映射规则,可以在OnTokenValidated事件回调中手动把aud声明补充到用户身份中:
options.Events.OnTokenValidated = context => { var audClaim = context.SecurityToken.Claims.FirstOrDefault(c => c.Type == "aud"); if (audClaim != null && !context.Principal.HasClaim(c => c.Type == "aud")) { ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("aud", audClaim.Value)); } return Task.CompletedTask; };
验证方法
你可以在任意需要授权的接口中打印当前用户的所有声明,确认声明的实际键名:
foreach (var claim in User.Claims) { System.Diagnostics.Debug.WriteLine($"声明类型:{claim.Type},值:{claim.Value}"); }
内容的提问来源于stack exchange,提问作者mooreds
相关产品推荐
相关产品推荐

