{"record":{"id":"0cbc4e4427f805a3","repo":"spring-projects/spring-security","slug":"invalid-request-0cbc4e","errorCode":"invalid_request","errorMessage":"OAuth 2.0 Client Registration Error: ${ex.getMessage()}","messagePattern":"OAuth 2\\.0 Client Registration Error: (.+?)","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":400,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ClientRegistrationAuthenticationConverter.java","lineNumber":63,"sourceCode":" */\npublic final class OAuth2ClientRegistrationAuthenticationConverter implements AuthenticationConverter {\n\n\tprivate final HttpMessageConverter<OAuth2ClientRegistration> clientRegistrationHttpMessageConverter = new OAuth2ClientRegistrationHttpMessageConverter();\n\n\t@Override\n\tpublic Authentication convert(HttpServletRequest request) {\n\t\tAuthentication principal = SecurityContextHolder.getContext().getAuthentication();\n\n\t\tOAuth2ClientRegistration clientRegistration;\n\t\ttry {\n\t\t\tclientRegistration = this.clientRegistrationHttpMessageConverter.read(OAuth2ClientRegistration.class,\n\t\t\t\t\tnew ServletServerHttpRequest(request));\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tOAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST,\n\t\t\t\t\t\"OAuth 2.0 Client Registration Error: \" + ex.getMessage(),\n\t\t\t\t\t\"https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.2\");\n\t\t\tthrow new OAuth2AuthenticationException(error, ex);\n\t\t}\n\n\t\treturn new OAuth2ClientRegistrationAuthenticationToken(principal, clientRegistration);\n\t}\n\n}\n","sourceCodeStart":45,"sourceCodeEnd":70,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ClientRegistrationAuthenticationConverter.java#L45-L70","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Look at the cause (ex.getMessage() appears in the description) to see the actual parse/validation failure.","Validate the registration JSON against RFC 7591 metadata: required fields such as client_name, redirect_uris, grant_types, token_endpoint_auth_method.","Send the request with Content-Type: application/json and a syntactically valid JSON body.","Catch OAuth2AuthenticationException on the client side and surface the error_description from the registration endpoint's 400 response."],"exampleFix":"// before: malformed registration payload\n{\"client_name\":\"my-app\",\"redirect_uris\":\"https://app/callback\"}\n// after\n{\"client_name\":\"my-app\",\n \"redirect_uris\":[\"https://app.example.com/callback\"],\n \"grant_types\":[\"authorization_code\"],\n \"token_endpoint_auth_method\":\"client_secret_basic\"}","handlingStrategy":"try-catch","validationCode":"function validateRegistrationPayload(payload) {\n  const errors = [];\n  if (typeof payload !== 'object' || payload === null) errors.push('body must be a JSON object');\n  if (!Array.isArray(payload.redirect_uris) || payload.redirect_uris.length === 0) errors.push('redirect_uris must be a non-empty array');\n  if (!Array.isArray(payload.grant_types) || payload.grant_types.length === 0) errors.push('grant_types must be a non-empty array');\n  if (!payload.token_endpoint_auth_method) errors.push('token_endpoint_auth_method is required');\n  return errors;\n}","typeGuard":"function isRegistrationPayload(p) {\n  return p != null && typeof p === 'object'\n    && typeof p.client_name === 'string'\n    && Array.isArray(p.redirect_uris)\n    && Array.isArray(p.grant_types);\n}","tryCatchPattern":"try {\n  response = registerClient(registrationJson);\n} catch (OAuth2AuthenticationException e) {\n  OAuth2Error err = e.getError();\n  logger.error(\"Client registration failed ({}): {} cause={}\",\n      err.getErrorCode(), err.getDescription(),\n      e.getCause() != null ? e.getCause().getMessage() : \"n/a\");\n  // fix payload per the cause message and retry\n}","preventionTips":["Validate registration JSON against RFC 7591 metadata fields before POSTing.","Always set Content-Type: application/json on registration requests.","Generate payloads programmatically (serialize typed objects) rather than hand-writing JSON.","Log the cause of OAuth2AuthenticationException — the wrapped exception holds the real parse error."],"tags":["oauth2","client-registration","rfc7591","invalid-json"],"backgroundTag":"invalid-json-response","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}