使用手动配置的 AddOpenIdConnect - SecurityTokenSignatureKeyNotFoundException

AddOpenIdConnect with manual Configuration - SecurityTokenSignatureKeyNotFoundException

现有系统

我们正在使用 Identity Server 4 为 Google、Azure 或其他外部提供商提供单点登录功能,没有任何问题。我们所要做的就是添加客户详细信息和权限 url 或 disco url(例如 .well-known/openid-configuration),一切都会按预期进行。

场景

我们的一位外部身份提供者表示他们无法提供 public 发现文档 url,并且他们仅在内部将其设为私有。然后他们提供了 Json 文件(其中包含 url 提供的确切 json 文本)。因此,我们正在尝试使用该 json 文件中的值通过使用 AddOpenIdConnectOpenIdConnectConfiguration.

手动设置所有这些端点 url 和设置

它正确地重定向到授权请求的外部提供商,我们可以登录外部系统。但是当请求返回到我们的 Idsrv4 时,它无法验证 id_token。我们得到 SecurityTokenSignatureKeyNotFoundException。我们确实尝试设置 JwksUri,但仍然没有成功。

我通过使用 Demo Identity 服务器成功复制了相同的行为,请参阅以下内容:

.AddOpenIdConnect("manualidsrv", "IdentityServer Manual", options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                options.SignOutScheme = IdentityServerConstants.SignoutScheme;

                options.Authority = "https://demo.identityserver.io/";
                options.ClientId = "login";
                options.ResponseType = "id_token";
                options.SaveTokens = true;

                options.Configuration = new OpenIdConnectConfiguration
                {
                    Issuer = "https://demo.identityserver.io",
                    JwksUri = "https://demo.identityserver.io/.well-known/openid-configuration/jwks",
                    AuthorizationEndpoint = "https://demo.identityserver.io/connect/authorize",
                    TokenEndpoint = "https://demo.identityserver.io/connect/token",
                    UserInfoEndpoint = "https://demo.identityserver.io/connect/userinfo",
                    EndSessionEndpoint = "https://demo.identityserver.io/connect/endsession",
                    ResponseTypesSupported =
                    {
                        "code",
                        "token",
                        "id_token",
                        "id_token token",
                        "code id_token",
                        "code token",
                        "code id_token token"
                    },
                    GrantTypesSupported = { 
                        "authorization_code",
                        "client_credentials",
                        "refresh_token",
                        "implicit",
                        "password",
                        "urn:ietf:params:oauth:grant-type:device_code"
                    },
                    ResponseModesSupported =
                    {
                        "form_post",
                        "query",
                        "fragment"
                    },
                    IdTokenSigningAlgValuesSupported = { "RS256" },
                    
            };

我们得到的错误是

SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match keys:
kid: '3BA75FA392E4DAFAC2737B5B4644AA85',
token: '{"alg":"RS256","kid":"3BA75FA392E4DAFAC2737B5B4644AA85","typ":"JWT"}.{"nbf":1596656241,"exp":1596656541,"iss":"https://demo.identityserver.io","aud":"login","nonce":"637322530390217907.xxx","iat":1596656241,"s_hash":"exiANrEFoXVDwA5BK1mGTg","sid":"D90FD8D4FA73AD590E3C53155375EA49","sub":"1","auth_time":1596652196,"idp":"local","name":"Alice Smith","given_name":"Alice","family_name":"Smith","email":"AliceSmith@email.com","email_verified":true,"website":"http://alice.com","amr":["pwd"]}'.

我尝试检查 jwksUri:https://demo.identityserver.io/.well-known/openid-configuration/jwks,我可以在那里看到正确的孩子“3BA75FA392E4DAFAC2737B5B4644AA85”。

因此,在我看来,如果我们手动设置配置,Idsrv4 不会正确加载这些密钥。

有一些建议使用 ConfigurationManager 手动加载签名密钥,如下所示:

new ConfigurationManager<OpenIdConnectConfiguration>($"DiscoveryEndpointUrl", new OpenIdConnectConfigurationRetriever());

但是,由于我们无权访问该端点 url,它对我们不起作用。

是否有强制 Idsrv 从 jwksUri 加载密钥或手动提供密钥的方法?

您能否建议解决此签名密钥异常?

一种解决方法可能是将来自提供商的发现文档放入 JSON 文档中,并将其作为静态资源包含在您的 IdentityServer 中?。然后只需将 link 添加到配置中的静态端点?

我怀疑 IdentityServer 是否关心该文档是否在本地托管。