如何在无kid的情况下验证Token?附IDX10503异常问题
遇到的异常
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: 'IDX10503: Signature validation failed. Token does not have a kid. Keys tried: '[PII of type 'System.Text.StringBuilder' is hidden. For more details, see官方PII文档]'. Number of keys in TokenValidationParameters: '1'.
Number of keys in Configuration: '0'.
Exceptions caught:
'[PII of type 'System.Text.StringBuilder' is hidden. For more details, see官方PII文档]'.
token: '[PII of type 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken' is hidden. For more details, see官方PII文档]'. See IDX10503官方文档 for details.'
可行性结论
完全可行。默认情况下Microsoft IdentityModel库依赖令牌头中的kid(密钥ID)字段匹配验证密钥,但通过自定义配置可以跳过kid校验,直接使用指定密钥验证令牌签名。
实现步骤
1. 直接指定验证密钥
在TokenValidationParameters中显式设置IssuerSigningKey,不依赖动态密钥发现(如从OpenID元数据端点获取密钥)。
2. 自定义密钥解析逻辑
通过设置IssuerSigningKeyResolver委托,强制返回指定的验证密钥,忽略令牌中的kid字段(即使不存在也不影响)。
示例代码(ASP.NET Core)
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; using System.Collections.Generic; services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = "你的签发者标识", ValidAudience = "你的受众标识", // 指定对称加密密钥(非对称密钥可使用RsaSecurityKey) IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("你的密钥字符串")), // 自定义密钥解析器,忽略kid直接返回指定密钥 IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => { return new List<SecurityKey> { validationParameters.IssuerSigningKey }; } }; });
注意事项
- 确保完全信任令牌的签发方:跳过
kid匹配后,所有无kid的令牌都会使用你指定的密钥验证,需避免密钥泄露或被非法使用。 - 非对称密钥场景同样适用:只需将
IssuerSigningKey替换为对应的RsaSecurityKey或EcdsaSecurityKey实例即可。
内容的提问来源于stack exchange,提问作者Somesh Banjare

