{"record":{"id":"3a13d2d11cc98a95","repo":"elsa-workflows/elsa-core","slug":"the-identity-provider-did-not-provide-signing-keys","errorCode":null,"errorMessage":"The identity provider did not provide signing keys.","messagePattern":"The identity provider did not provide signing keys\\.","errorType":"exception","errorClass":"OpenIdConnectAuthenticationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.ExternalAuthentication.OpenIdConnect/Services/OpenIdConnectExternalAuthenticationAdapter.cs","lineNumber":229,"sourceCode":"        return new(validation.ClaimsIdentity);\n    }\n\n    private Uri GetCallbackUri(EffectiveIdentityProviderConnection connection, BrokerTransactionPurpose purpose)\n    {\n        var baseUri = options.Value.Redirects.ExternalCallbackBaseUri ?? throw new OpenIdConnectAuthenticationException(\"The deployment callback base URI is not configured.\");\n        return ExternalAuthenticationCallbackUris.GetAuthorizationCallbackUri(baseUri, connection.Connection, purpose);\n    }\n\n    private Uri GetLogoutCallbackUri(EffectiveIdentityProviderConnection connection)\n    {\n        var baseUri = options.Value.Redirects.ExternalCallbackBaseUri ?? throw new OpenIdConnectAuthenticationException(\"The deployment callback base URI is not configured.\");\n        return ExternalAuthenticationCallbackUris.GetLogoutCallbackUri(baseUri, connection.Connection.Key);\n    }\n\n    private async Task<IEnumerable<SecurityKey>> GetSigningKeysAsync(Uri? jwksUri, CancellationToken cancellationToken)\n    {\n        if (jwksUri is null)\n            throw new OpenIdConnectAuthenticationException(\"The identity provider did not provide signing keys.\");\n        var response = await providerHttpClient.GetAsync(jwksUri, ProviderResponseKind.SigningKeys, cancellationToken);\n        if (!response.IsSuccessStatusCode)\n            throw new OpenIdConnectAuthenticationException(\"The identity provider signing keys could not be resolved.\");\n        try\n        {\n            return new JsonWebKeySet(response.ReadBodyAsUtf8()).Keys;\n        }\n        catch (JsonException)\n        {\n            throw new OpenIdConnectAuthenticationException(\"The identity provider signing keys were invalid.\");\n        }\n    }\n\n    private static IReadOnlyDictionary<string, IReadOnlyCollection<string>> ProjectClaims(System.Security.Claims.ClaimsPrincipal principal, ClaimProjection projection)\n    {\n        if (projection.MaximumClaimCount <= 0 || projection.MaximumValueLength <= 0 || projection.MaximumTotalBytes <= 0)\n            return new Dictionary<string, IReadOnlyCollection<string>>(StringComparer.Ordinal);\n","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.ExternalAuthentication.OpenIdConnect/Services/OpenIdConnectExternalAuthenticationAdapter.cs#L211-L247","documentation":"GetSigningKeysAsync fetches the provider's JWKS to validate ID tokens, but requires metadata.TokenEndpoint's discovery counterpart jwks_uri. If the provider metadata did not include a jwks_uri, the adapter cannot obtain keys and throws. Also thrown when the metadata itself was incomplete.","triggerScenarios":"GetSigningKeysAsync is called with jwksUri == null, i.e. the OIDC discovery document (or manually supplied metadata) lacks the jwks_uri field.","commonSituations":"Misconfigured WellKnown/metadata endpoint pointing at a plain OAuth2 (non-OIDC) server that has no jwks_uri; discovery document cached from a misconfigured provider; custom metadata overrides omitting jwks_uri; typo'd authority URL returning an HTML page parsed as sparse metadata.","solutions":["Verify the provider's discovery document (issuer + /.well-known/openid-configuration) actually contains jwks_uri.","Correct the connection's authority/issuer URL so discovery hits the real OIDC metadata.","If metadata is manually supplied, add the jwks_uri property.","Clear any cached discovery metadata after fixing the provider configuration."],"exampleFix":"// before: manual metadata missing keys\nvar metadata = new ProviderMetadata { TokenEndpoint = tokenUri };\n// after\nvar metadata = new ProviderMetadata { TokenEndpoint = tokenUri, JwksUri = new Uri(\"https://idp.example.com/.well-known/jwks.json\") };","handlingStrategy":"validation","validationCode":"var metadata = await discovery.GetMetadataAsync(settings, ct);\nif (metadata.JwksUri is null)\n    throw new InvalidOperationException($\"Discovery for '{settings.Issuer}' returned no jwks_uri; verify the issuer is an OIDC provider.\");","typeGuard":null,"tryCatchPattern":"try { await adapter.ValidateIdTokenAsync(idToken, settings, metadata, ct); }\ncatch (OpenIdConnectAuthenticationException ex) when (ex.Message.Contains(\"signing keys\"))\n{ logger.LogError(ex, \"Provider metadata for {Issuer} lacks jwks_uri\", settings.Issuer); return Results.Problem(\"Identity provider metadata is incomplete.\", statusCode: 502); }","preventionTips":["Point connections at real OIDC providers whose discovery document includes jwks_uri","Test discovery (curl issuer/.well-known/openid-configuration) when onboarding a provider","If supplying metadata manually, always include jwks_uri"],"tags":["openid-connect","jwks","signing-keys","discovery","configuration"],"backgroundTag":"missing-required-config-field","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}