spring-projects/spring-security · error · OAuth2AuthenticationException

missing_signature_verifier

missing_signature_verifier

Error message

Failed to find a Signature Verifier for Client Registration: '${registrationId}'. Check to ensure you have configured the JwkSet URI.

What it means

OidcIdTokenDecoderFactory builds a JwtDecoder for a ClientRegistration's ID Tokens. If the registration's JWS algorithm is an asymmetric signature algorithm (e.g. RS256), a JWK Set URI is required to fetch the provider's public keys. When the registration has no jwkSetUri configured, the factory throws OAuth2AuthenticationException with code 'missing_signature_verifier'.

Source

Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java:170

			// the TLS server validation MAY be used to validate the issuer in place of
			// checking the token signature.
			// The Client MUST validate the signature of all other ID Tokens according to
			// JWS [JWS]
			// using the algorithm specified in the JWT alg Header Parameter.
			// The Client MUST use the keys provided by the Issuer.
			//
			// 7. The alg value SHOULD be the default of RS256 or the algorithm sent by
			// the Client
			// in the id_token_signed_response_alg parameter during Registration.

			String jwkSetUri = clientRegistration.getProviderDetails().getJwkSetUri();
			if (!StringUtils.hasText(jwkSetUri)) {
				OAuth2Error oauth2Error = new OAuth2Error(MISSING_SIGNATURE_VERIFIER_ERROR_CODE,
						"Failed to find a Signature Verifier for Client Registration: '"
								+ clientRegistration.getRegistrationId()
								+ "'. Check to ensure you have configured the JwkSet URI.",
						null);
				throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
			}
			return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).jwsAlgorithm((SignatureAlgorithm) jwsAlgorithm).build();
		}
		if (jwsAlgorithm != null && MacAlgorithm.class.isAssignableFrom(jwsAlgorithm.getClass())) {
			// https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
			//
			// 8. If the JWT alg Header Parameter uses a MAC based algorithm such as
			// HS256, HS384, or HS512,
			// the octets of the UTF-8 representation of the client_secret
			// corresponding to the client_id contained in the aud (audience) Claim
			// are used as the key to validate the signature.
			// For MAC based algorithms, the behavior is unspecified if the aud is
			// multi-valued or
			// if an azp value is present that is different than the aud value.
			String clientSecret = clientRegistration.getClientSecret();
			if (!StringUtils.hasText(clientSecret)) {
				OAuth2Error oauth2Error = new OAuth2Error(MISSING_SIGNATURE_VERIFIER_ERROR_CODE,
						"Failed to find a Signature Verifier for Client Registration: '"

View on GitHub (pinned to 96852e8860)

Solutions

  1. Configure the OIDC provider via issuer-uri so Spring fetches the JWK Set URI from .well-known/openid-configuration automatically.
  2. Or explicitly set the JWK Set URI: ClientRegistration.withSettings(s -> s.jwkSetUri("https://idp/.well-known/jwks.json")).
  3. In yaml, ensure spring.security.oauth2.client.provider.<id>.jwk-set-uri (or issuer-uri) is set for the registration's provider.
  4. If the provider truly uses HMAC (HS256) for id_tokens, switch registration/clientSecret handling so the MacAlgorithm branch is taken instead.
  5. Throw-site is OidcIdTokenDecoderFactory.buildDecoder — verify which factory instance/registration is being used.

Example fix

// before
ClientRegistration registration = ClientRegistration.withRegistrationId("my-idp")
    .clientId("cid").clientSecret("secret")
    .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
    .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
    .tokenUri("https://idp/token").build();
// after: add the JWK Set URI
    .scope("openid")
    .jwkSetUri("https://idp/.well-known/jwks.json")
    .clientName("My IdP")
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if (!StringUtils.hasText(registration.getProviderDetails()
        .getConfigurationMetadata().get("jwks_uri"))
    && !StringUtils.hasText(registration.getProviderDetails().getJwkSetUri())) {
    throw new IllegalStateException("jwkSetUri missing for " + registration.getRegistrationId());
}

Try / catch

try {
    JwtDecoder d = idTokenDecoderFactory.createDecoder(registration);
} catch (OAuth2AuthenticationException ex) {
    if ("missing_signature_verifier".equals(ex.getError().getErrorCode())) {
        throw new IllegalStateException(
            "Configure jwkSetUri for registration " + registration.getRegistrationId(), ex);
    }
}

Prevention

When it happens

Trigger: jwtDecoder() -> buildDecoder() for a ClientRegistration whose providerMetadata jwk_set_uri is null/empty while the configured JWS algorithm requires asymmetric verification — e.g. building an OidcIdTokenValidator or decoding an id_token for a registration created programmatically without discovery.

Common situations: ClientRegistration built with CommonOAuth2Provider or withRegistrationId without issuer-uri/oidc metadata, so jwkSetUri was never populated; manual ClientRegistration.withSettings(...) that forgot .jwkSetUri(...); Spring Boot property spring.security.oauth2.client.registration.* missing provider OIDC config.

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 spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/5ef13ed77569f7df. Report an issue: GitHub.