spring-projects/spring-security · error · OAuth2AuthenticationException

invalid_request

invalid_request

Error message

OAuth 2.0 Client Registration Error: ${ex.getMessage()}

What it means

OAuth2ClientRegistrationAuthenticationConverter wraps any exception raised while parsing a dynamic client registration request (RFC 7591) into an OAuth2AuthenticationException with code invalid_request and description "OAuth 2.0 Client Registration Error: <original message>". The catch-all in convert() means any failure deserializing/validating the registration JSON body surfaces under this single message, preserving the cause in the exception.

Source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ClientRegistrationAuthenticationConverter.java:63

 */
public final class OAuth2ClientRegistrationAuthenticationConverter implements AuthenticationConverter {

	private final HttpMessageConverter<OAuth2ClientRegistration> clientRegistrationHttpMessageConverter = new OAuth2ClientRegistrationHttpMessageConverter();

	@Override
	public Authentication convert(HttpServletRequest request) {
		Authentication principal = SecurityContextHolder.getContext().getAuthentication();

		OAuth2ClientRegistration clientRegistration;
		try {
			clientRegistration = this.clientRegistrationHttpMessageConverter.read(OAuth2ClientRegistration.class,
					new ServletServerHttpRequest(request));
		}
		catch (Exception ex) {
			OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST,
					"OAuth 2.0 Client Registration Error: " + ex.getMessage(),
					"https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.2");
			throw new OAuth2AuthenticationException(error, ex);
		}

		return new OAuth2ClientRegistrationAuthenticationToken(principal, clientRegistration);
	}

}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Look at the cause (ex.getMessage() appears in the description) to see the actual parse/validation failure.
  2. Validate the registration JSON against RFC 7591 metadata: required fields such as client_name, redirect_uris, grant_types, token_endpoint_auth_method.
  3. Send the request with Content-Type: application/json and a syntactically valid JSON body.
  4. Catch OAuth2AuthenticationException on the client side and surface the error_description from the registration endpoint's 400 response.

Example fix

// before: malformed registration payload
{"client_name":"my-app","redirect_uris":"https://app/callback"}
// after
{"client_name":"my-app",
 "redirect_uris":["https://app.example.com/callback"],
 "grant_types":["authorization_code"],
 "token_endpoint_auth_method":"client_secret_basic"}
Defensive patterns

Strategy: try-catch

Validate before calling

function validateRegistrationPayload(payload) {
  const errors = [];
  if (typeof payload !== 'object' || payload === null) errors.push('body must be a JSON object');
  if (!Array.isArray(payload.redirect_uris) || payload.redirect_uris.length === 0) errors.push('redirect_uris must be a non-empty array');
  if (!Array.isArray(payload.grant_types) || payload.grant_types.length === 0) errors.push('grant_types must be a non-empty array');
  if (!payload.token_endpoint_auth_method) errors.push('token_endpoint_auth_method is required');
  return errors;
}

Type guard

function isRegistrationPayload(p) {
  return p != null && typeof p === 'object'
    && typeof p.client_name === 'string'
    && Array.isArray(p.redirect_uris)
    && Array.isArray(p.grant_types);
}

Try / catch

try {
  response = registerClient(registrationJson);
} catch (OAuth2AuthenticationException e) {
  OAuth2Error err = e.getError();
  logger.error("Client registration failed ({}): {} cause={}",
      err.getErrorCode(), err.getDescription(),
      e.getCause() != null ? e.getCause().getMessage() : "n/a");
  // fix payload per the cause message and retry
}

Prevention

When it happens

Trigger: A POST to the client registration endpoint with a body that fails to parse as a ClientRegistration payload (invalid JSON, wrong field types, missing required fields like redirect_uris or token_endpoint_auth_method, or any other exception thrown by the underlying request parser).

Common situations: Sending registration metadata with a wrong-typed field (e.g. numeric grant type); omitting required RFC 7591 fields; sending a content-type other than application/json; malformed JSON from a template or script; provisioning clients with an automation script that has drifted from the expected schema.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/0cbc4e4427f805a3. Report an issue: GitHub.