VB.NET使用OpenIdConnect出现IDX10501签名验证失败问题求助
问题根因
你只在应用启动时一次性拉取了OpenID Connect身份服务商的签名密钥,没有设置自动刷新逻辑。当身份服务商定期(你遇到的周期是10-12小时)轮换签名密钥后,本地缓存的旧密钥无法匹配新签发Token的签名,就会抛出IDX10501错误。重新保存配置会触发应用重启,再次拉取最新密钥所以临时恢复,等下一次密钥轮换就会复现问题。
解决步骤
1. 替换静态密钥配置逻辑
删掉手动拉取JWKS密钥的代码,依赖ConfigurationManager自带的配置自动刷新能力,不要将密钥写死为启动时拉取的静态值。
2. 配置自动刷新和密钥解析规则
调整ConfigurationManager的刷新间隔适配服务商的密钥轮换周期,同时配置密钥解析委托,当签名匹配失败时自动拉取最新密钥。
3. 移除冗余同步调用
不要用.Result同步调用异步方法避免线程死锁,中间件会自动处理配置的异步拉取逻辑。
修改后的核心代码
Public Sub ConfigureAuth(ByVal app As IAppBuilder) Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 ' 配置ConfigurationManager,设置自动刷新间隔 Dim configurationManager = New ConfigurationManager(Of OpenIdConnectConfiguration)( $"{authority}/.well-known/openid-configuration", New OpenIdConnectConfigurationRetriever(), New HttpDocumentRetriever()) With { .AutomaticRefreshInterval = TimeSpan.FromHours(6), ' 每6小时主动刷新一次配置和密钥 .RefreshInterval = TimeSpan.FromMinutes(1) ' 校验失败后最短1分钟可重试刷新 } ' 删掉原来手动拉取discoveryDocument和signingKeys的两行代码,也可以删掉整个GetSecurityKeyAsync方法 app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType) IdentityModelEventSource.ShowPII = True app.UseCookieAuthentication(New CookieAuthenticationOptions()) app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions With { .GetClaimsFromUserInfoEndpoint = True, .ClientId = clientId, .ClientSecret = clientSecret, .Authority = authority, .ResponseType = OpenIdConnectResponseType.Code, .RedirectUri = redirectUri, .CallbackPath = Microsoft.Owin.PathString.FromUriComponent(New Uri(callBackPath)), .TokenValidationParameters = New TokenValidationParameters() With { ' 删掉原来的IssuerSigningKeys配置,换成以下配置 .ConfigurationManager = configurationManager, .IssuerSigningKeyResolver = Function(token, securityToken, kid, validationParameters) ' 密钥匹配失败时自动拉取最新配置获取对应kid的密钥 Dim latestConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result Return latestConfig.SigningKeys.Where(Function(k) k.KeyId = kid) End Function, .RequireSignedTokens = True, .RequireExpirationTime = True, .ValidateLifetime = True, .ValidateAudience = True, .ValidAudience = clientId, .ValidateIssuer = True, .ValidIssuer = authority, .SaveSigninToken = True }, ' 其余Notifications配置保持不变 .Notifications = New OpenIdConnectAuthenticationNotifications With { .RedirectToIdentityProvider = Function(n) n.ProtocolMessage.SetParameter(acr, acrValues) n.Response.Redirect(callBackPath) n.ProtocolMessage.RedirectUri = callBackPath Return Task.FromResult(0) End Function, .SecurityTokenValidated = Function(context) Dim anc = Convert.ToString(context.ProtocolMessage.AccessToken) Dim rawAccessToken As String = context.ProtocolMessage.AccessToken Dim rawIdToken As String = context.ProtocolMessage.IdToken Dim handler = New JwtSecurityTokenHandler() Dim accessToken = handler.ReadJwtToken(rawAccessToken) Dim idToken = handler.ReadJwtToken(rawIdToken) context.Response.Redirect(callBackPath) If (TypeOf context.AuthenticationTicket.Identity Is ClaimsIdentity) Then Dim identity As ClaimsIdentity = New ClaimsIdentity Dim claimsIdentity As ClaimsIdentity = CType(context.AuthenticationTicket.Identity, ClaimsIdentity) Dim userId As String = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value identity.AddClaim(New Claim(ClaimTypes.GivenName, userId)) End If Return Task.CompletedTask End Function } }) End Sub
内容的提问来源于stack exchange,提问作者tushi0407
相关产品推荐
相关产品推荐

