{"record":{"id":"2b029521b0d577bc","repo":"spring-projects/spring-security","slug":"invalid-request-2b0295","errorCode":"invalid_request","errorMessage":"invalid_request","messagePattern":"invalid_request","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/JwtClientAssertionAuthenticationConverter.java","lineNumber":65,"sourceCode":"public final class JwtClientAssertionAuthenticationConverter implements AuthenticationConverter {\n\n\tprivate static final ClientAuthenticationMethod JWT_CLIENT_ASSERTION_AUTHENTICATION_METHOD = new ClientAuthenticationMethod(\n\t\t\t\"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\");\n\n\t@Override\n\tpublic @Nullable Authentication convert(HttpServletRequest request) {\n\t\tMultiValueMap<String, String> parameters = OAuth2EndpointUtils.getFormParameters(request);\n\n\t\tif (parameters.getFirst(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE) == null\n\t\t\t\t|| parameters.getFirst(OAuth2ParameterNames.CLIENT_ASSERTION) == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// client_assertion_type (REQUIRED)\n\t\tString clientAssertionType = parameters.getFirst(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE);\n\t\tList<String> clientAssertionTypeParams = parameters.get(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE);\n\t\tif (clientAssertionTypeParams == null || clientAssertionTypeParams.size() != 1) {\n\t\t\tthrow new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);\n\t\t}\n\t\tif (!JWT_CLIENT_ASSERTION_AUTHENTICATION_METHOD.getValue().equals(clientAssertionType)) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// client_assertion (REQUIRED)\n\t\tString jwtAssertion = parameters.getFirst(OAuth2ParameterNames.CLIENT_ASSERTION);\n\t\tList<String> clientAssertionParams = parameters.get(OAuth2ParameterNames.CLIENT_ASSERTION);\n\t\tif (clientAssertionParams == null || clientAssertionParams.size() != 1) {\n\t\t\tthrow new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);\n\t\t}\n\n\t\t// client_id (OPTIONAL as per specification but REQUIRED by this implementation)\n\t\tString clientId = parameters.getFirst(OAuth2ParameterNames.CLIENT_ID);\n\t\tList<String> clientIdParams = parameters.get(OAuth2ParameterNames.CLIENT_ID);\n\t\tif (!StringUtils.hasText(clientId) || clientIdParams == null || clientIdParams.size() != 1) {\n\t\t\tthrow new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);\n\t\t}","sourceCodeStart":47,"sourceCodeEnd":83,"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/JwtClientAssertionAuthenticationConverter.java#L47-L83","documentation":"Thrown by JwtClientAssertionAuthenticationConverter.convert() when the client_assertion_type parameter is present but not exactly one value. The JWT client authentication flow requires a single client_assertion_type; duplicates trigger an immediate invalid_request before the value is even checked against 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'.","triggerScenarios":"Token request containing client_assertion_type twice, or zero times while some other parameter triggered converter entry (e.g. client_assertion present but assertion_type missing).","commonSituations":"Merging parameter maps that both contain client_assertion_type; a client library that adds the parameter while user code also adds it; omitting the parameter entirely while sending client_assertion.","solutions":["Send client_assertion_type exactly once with value 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'.","Ensure client_assertion_type is included whenever client_assertion is sent.","Use set() not add() when building the parameter map to avoid duplicates.","Verify no query-string + body duplication of the parameter."],"exampleFix":"// before\nform.add(\"client_assertion\", jwt); // missing client_assertion_type\n// after\nform.set(\"client_assertion_type\", \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\");\nform.set(\"client_assertion\", jwt);","handlingStrategy":"validation","validationCode":"boolean validAssertionTypeParams(MultiValueMap<String, String> form) {\n    List<String> v = form.get(\"client_assertion_type\");\n    return v != null && v.size() == 1\n        && \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\".equals(v.get(0));\n}","typeGuard":null,"tryCatchPattern":"try { tokenResponse = client.token(request); }\ncatch (OAuth2AuthenticationException e) {\n    if (\"invalid_request\".equals(e.getError().getErrorCode())) { log.error(\"client_assertion_type must be present exactly once\"); }\n    throw e;\n}","preventionTips":["Always pair client_assertion with exactly one client_assertion_type parameter.","Build assertion request parameters in a single helper to avoid scattered additions."],"tags":["oauth2","jwt","client-authentication","request-parameters"],"backgroundTag":"missing-required-argument","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}