OpenIddict 6 + .NET 9自定义OIDC提供商令牌验证失败求助
问题概述
在.NET 9环境下使用OpenIddict 6搭建登录服务,已支持用户名密码、Google、Facebook认证,现在对接一个无.well-known配置端点的自定义OIDC提供商(非.NET实现),跳转及返回流程正常,Issuer验证通过,但令牌始终验证失败。
错误信息
error:invalid_token
error_description:The signing key associated to the specified token was not found.
error_uri:https://documentation.openiddict.com/errors/ID2090
客户端注册配置
var registration = new OpenIddictClientRegistration { Issuer = new Uri(oidcProvider.Issuer, UriKind.Absolute), ProviderName = oidcProvider.ProviderName, ProviderDisplayName = oidcProvider.ProviderDisplayName, ClientId = oidcProvider.ClientId, ClientSecret = oidcProvider.ClientSecret, RedirectUri = new Uri($"callback/login/{oidcProvider.ProviderName}", UriKind.Relative), Scopes = { OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Profile, OpenIddictConstants.Scopes.Email }, Configuration = new OpenIddictConfiguration { Issuer = new Uri(oidcProvider.Issuer, UriKind.Absolute), AuthorizationEndpoint = new Uri(oidcProvider.AuthorityUrl, UriKind.Absolute), TokenEndpoint = new Uri(oidcProvider.TokenEndpoint, UriKind.Absolute), ResponseTypesSupported = { OpenIddictConstants.ResponseTypes.Code }, // Use Authorization Code Flow TokenEndpointAuthMethodsSupported = { OpenIddictConstants.ClientAuthenticationMethods.ClientSecretPost }, JsonWebKeySetUri = new Uri(oidcProvider.JWKSEndpoint, UriKind.Absolute), CodeChallengeMethodsSupported = { OpenIddictConstants.CodeChallengeMethods.Sha256 }, GrantTypesSupported = { OpenIddictConstants.GrantTypes.AuthorizationCode }, } }; options.AddRegistration(registration);
关键日志片段
The event OpenIddict.Client.OpenIddictClientEvents+ValidateTokenContext was successfully processed by OpenIddict.Client.OpenIddictClientHandlers+Protection+RemoveDisallowedCharacters. dbug: OpenIddict.Client.OpenIddictClientDispatcher[0] The event OpenIddict.Client.OpenIddictClientEvents+ValidateTokenContext was successfully processed by OpenIddict.Client.OpenIddictClientHandlers+Protection+ValidateReferenceTokenIdentifier. trce: OpenIddict.Client.OpenIddictClientDispatcher[0] An error occurred while validating the token 'Some Token Here'. Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed. No security keys were provided to validate the signature. at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignature(JsonWebToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignatureAndIssuerSecurityKey(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateJWSAsync(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) dbug: OpenIddict.Client.OpenIddictClientDispatcher[0]
排查步骤
1. 验证JWKS端点可用性与返回内容
直接访问配置的JsonWebKeySetUri对应的URL,确认:
- 端点返回200状态码,且返回的JWKS结构符合标准格式
- JWKS中包含有效的签名密钥(非空数组)
2. 匹配令牌算法与JWKS密钥算法
解码令牌(可使用JWT解码工具),查看令牌头的alg字段(如RS256、HS256),确认JWKS中存在对应算法的密钥:
- 若令牌用
RS256签名,但JWKS仅提供HS256密钥,会直接导致验证失败
3. 核对令牌kid与JWKS密钥ID
解码令牌头获取kid值,检查JWKS中的密钥是否有完全匹配的kid:
- 自定义提供商可能存在
kid大小写、格式不一致的问题,需确保两者完全一致
4. 检查OpenIddict的JWKS加载逻辑
启用Microsoft.IdentityModel的Debug级日志,查看OpenIddict是否成功加载JWKS:
// 在appsettings.json中添加日志配置 "Logging": { "LogLevel": { "Microsoft.IdentityModel": "Debug" } }
若日志显示无法获取JWKS(如网络不通、端点返回错误),需排查网络连通性或端点配置正确性。
5. 手动加载JWKS密钥调试
如果自动加载存在问题,可尝试手动加载密钥并添加到配置中,验证是否能解决问题:
var httpClient = new HttpClient(); var jwks = await httpClient.GetFromJsonAsync<JsonWebKeySet>(oidcProvider.JWKSEndpoint); registration.Configuration.JsonWebKeys.AddRange(jwks.GetSigningKeys());
若手动加载后验证成功,说明OpenIddict自动加载逻辑可能对自定义JWKS格式兼容性不足,需调整提供商的JWKS返回格式。
6. 确认令牌类型
日志中触发了ValidateReferenceTokenIdentifier处理,需确认第三方返回的是自包含JWT令牌而非引用令牌:
- 若为引用令牌,需配置OpenIddict调用提供商的令牌 introspection 端点验证,但自定义提供商可能不支持该功能,需与提供商确认令牌类型。
内容的提问来源于stack exchange,提问作者runxc1 Bret Ferrier

