elsa-workflows/elsa-core · error · OpenIdConnectAuthenticationException

The identity provider did not provide signing keys.

Error message

The identity provider did not provide signing keys.

What it means

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.

Solutions

  1. Verify the provider's discovery document (issuer + /.well-known/openid-configuration) actually contains jwks_uri.
  2. Correct the connection's authority/issuer URL so discovery hits the real OIDC metadata.
  3. If metadata is manually supplied, add the jwks_uri property.
  4. Clear any cached discovery metadata after fixing the provider configuration.

Example fix

// before: manual metadata missing keys
var metadata = new ProviderMetadata { TokenEndpoint = tokenUri };
// after
var metadata = new ProviderMetadata { TokenEndpoint = tokenUri, JwksUri = new Uri("https://idp.example.com/.well-known/jwks.json") };
Defensive patterns

Strategy: validation

Validate before calling

var metadata = await discovery.GetMetadataAsync(settings, ct);
if (metadata.JwksUri is null)
    throw new InvalidOperationException($"Discovery for '{settings.Issuer}' returned no jwks_uri; verify the issuer is an OIDC provider.");

Try / catch

try { await adapter.ValidateIdTokenAsync(idToken, settings, metadata, ct); }
catch (OpenIdConnectAuthenticationException ex) when (ex.Message.Contains("signing keys"))
{ logger.LogError(ex, "Provider metadata for {Issuer} lacks jwks_uri", settings.Issuer); return Results.Problem("Identity provider metadata is incomplete.", statusCode: 502); }

Prevention

When it happens

Trigger: GetSigningKeysAsync is called with jwksUri == null, i.e. the OIDC discovery document (or manually supplied metadata) lacks the jwks_uri field.

Common situations: 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.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/3a13d2d11cc98a95. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.ExternalAuthentication.OpenIdConnect/Services/OpenIdConnectExternalAuthenticationAdapter.cs:229

        return new(validation.ClaimsIdentity);
    }

    private Uri GetCallbackUri(EffectiveIdentityProviderConnection connection, BrokerTransactionPurpose purpose)
    {
        var baseUri = options.Value.Redirects.ExternalCallbackBaseUri ?? throw new OpenIdConnectAuthenticationException("The deployment callback base URI is not configured.");
        return ExternalAuthenticationCallbackUris.GetAuthorizationCallbackUri(baseUri, connection.Connection, purpose);
    }

    private Uri GetLogoutCallbackUri(EffectiveIdentityProviderConnection connection)
    {
        var baseUri = options.Value.Redirects.ExternalCallbackBaseUri ?? throw new OpenIdConnectAuthenticationException("The deployment callback base URI is not configured.");
        return ExternalAuthenticationCallbackUris.GetLogoutCallbackUri(baseUri, connection.Connection.Key);
    }

    private async Task<IEnumerable<SecurityKey>> GetSigningKeysAsync(Uri? jwksUri, CancellationToken cancellationToken)
    {
        if (jwksUri is null)
            throw new OpenIdConnectAuthenticationException("The identity provider did not provide signing keys.");
        var response = await providerHttpClient.GetAsync(jwksUri, ProviderResponseKind.SigningKeys, cancellationToken);
        if (!response.IsSuccessStatusCode)
            throw new OpenIdConnectAuthenticationException("The identity provider signing keys could not be resolved.");
        try
        {
            return new JsonWebKeySet(response.ReadBodyAsUtf8()).Keys;
        }
        catch (JsonException)
        {
            throw new OpenIdConnectAuthenticationException("The identity provider signing keys were invalid.");
        }
    }

    private static IReadOnlyDictionary<string, IReadOnlyCollection<string>> ProjectClaims(System.Security.Claims.ClaimsPrincipal principal, ClaimProjection projection)
    {
        if (projection.MaximumClaimCount <= 0 || projection.MaximumValueLength <= 0 || projection.MaximumTotalBytes <= 0)
            return new Dictionary<string, IReadOnlyCollection<string>>(StringComparer.Ordinal);

View on GitHub (pinned to fe9217bdfa)