.NET Core 3.1 替换OpenIdConnectOptions发现文档端点不破坏授权流的方法
问题根因
你手动构造OpenIdConnectConfiguration并赋值给options.Configuration后,OIDC中间件会直接跳过自动元数据拉取流程,不会主动请求你配置的JwksUri地址加载签名公钥,导致SigningKeys集合为空,自然匹配不到对应kid的密钥,触发签名验证失败的报错。使用选项1、2时,中间件会自动完成发现文档拉取、JWKS公钥加载、元数据定时刷新的逻辑,所以运行正常。
解决方案
分两种场景选择适配的方案:
场景1:完全不使用自动发现,全手动配置
你需要手动加载JWKS中的签名密钥,填充到配置对象的SigningKeys属性中,修改后的选项3代码如下:
// 手动构造配置对象设置各URL var issuer = Configuration["AuthorityAddress"]; // 注意配置Key大小写和你配置文件保持一致 var authorization_endpoint = issuer + "/someidentityserver/authorize"; var token_endpoint = issuer + "/someidentityserver/token"; var userinfo_endpoint = issuer + "/someidentityserver/userinfo"; var jwks_uri = issuer + "/someidentityserver/jwks"; // 手动拉取JWKS并解析密钥 var httpClient = new HttpClient(); var jwksJson = httpClient.GetStringAsync(jwks_uri).GetAwaiter().GetResult(); var jwks = new JsonWebKeySet(jwksJson); options.Configuration = new OpenIdConnectConfiguration() { AuthorizationEndpoint = authorization_endpoint, JwksUri = jwks_uri, TokenEndpoint = token_endpoint, UserInfoEndpoint = userinfo_endpoint, Issuer = issuer, // 新增:填充签名密钥,可按需添加单个密钥或全部密钥 SigningKeys = { jwks.Keys } };
注意:该方案不会自动刷新签名密钥,如果身份服务更换了签名密钥,你需要重启应用才能加载新密钥,适合完全离线的部署场景。
场景2:仅替换自定义端点,保留自动发现能力(更推荐)
不需要完全手动构造配置对象,保留原有自动发现配置,通过OnMetadataReceived事件修改加载完成的元数据端点即可,既可以自定义端点,又能保留中间件自动加载JWKS、自动刷新元数据和密钥的原生能力,不会破坏原有授权流程:
private void SetOpenIdConnectOptions(OpenIdConnectOptions options) { options.ClientId = Configuration["ClientId"]; options.ClientSecret = Configuration["ClientSecret"]; options.ResponseType = "code"; options.ResponseMode = "query"; // 保留原有自动发现配置,选选项1或选项2都可以 options.Authority = Configuration["AuthorityAddress"]; // 新增元数据接收事件,修改自定义端点 options.Events.OnMetadataReceived = context => { var metadata = context.Metadata; var issuer = options.Authority.TrimEnd('/'); metadata.AuthorizationEndpoint = $"{issuer}/someidentityserver/authorize"; metadata.TokenEndpoint = $"{issuer}/someidentityserver/token"; metadata.UserInfoEndpoint = $"{issuer}/someidentityserver/userinfo"; metadata.JwksUri = $"{issuer}/someidentityserver/jwks"; return Task.CompletedTask; }; }
内容的提问来源于stack exchange,提问作者Fordy
相关产品推荐
相关产品推荐

