{"record":{"id":"3671ccfa4defc573","repo":"spring-projects/spring-security","slug":"oauth-2-0-parameter-parametername-3671cc","errorCode":null,"errorMessage":"OAuth 2.0 Parameter: ${parameterName}","messagePattern":"OAuth 2\\.0 Parameter: (.+?)","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/OAuth2EndpointUtils.java","lineNumber":128,"sourceCode":"\tstatic void validateAndAddDPoPParametersIfAvailable(HttpServletRequest request,\n\t\t\tMap<String, Object> additionalParameters) {\n\t\tfinal String dPoPProofHeaderName = OAuth2AccessToken.TokenType.DPOP.getValue();\n\t\tString dPoPProof = request.getHeader(dPoPProofHeaderName);\n\t\tif (StringUtils.hasText(dPoPProof)) {\n\t\t\tif (Collections.list(request.getHeaders(dPoPProofHeaderName)).size() != 1) {\n\t\t\t\tthrowError(OAuth2ErrorCodes.INVALID_REQUEST, dPoPProofHeaderName, ACCESS_TOKEN_REQUEST_ERROR_URI);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tadditionalParameters.put(\"dpop_proof\", dPoPProof);\n\t\t\t\tadditionalParameters.put(\"dpop_method\", request.getMethod());\n\t\t\t\tadditionalParameters.put(\"dpop_target_uri\", request.getRequestURL().toString());\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic void throwError(String errorCode, String parameterName, String errorUri) {\n\t\tOAuth2Error error = new OAuth2Error(errorCode, \"OAuth 2.0 Parameter: \" + parameterName, errorUri);\n\t\tthrow new OAuth2AuthenticationException(error);\n\t}\n\n\tstatic String normalizeUserCode(String userCode) {\n\t\tAssert.hasText(userCode, \"userCode cannot be empty\");\n\t\tStringBuilder sb = new StringBuilder(userCode.toUpperCase(Locale.ENGLISH).replaceAll(\"[^A-Z\\\\d]+\", \"\"));\n\t\tAssert.isTrue(sb.length() == 8, \"userCode must be exactly 8 alpha/numeric characters\");\n\t\tsb.insert(4, '-');\n\t\treturn sb.toString();\n\t}\n\n\tstatic boolean validateUserCode(String userCode) {\n\t\treturn (userCode != null && userCode.toUpperCase(Locale.ENGLISH).replaceAll(\"[^A-Z\\\\d]+\", \"\").length() == 8);\n\t}\n\n}\n","sourceCodeStart":110,"sourceCodeEnd":144,"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/OAuth2EndpointUtils.java#L110-L144","documentation":"OAuth2EndpointUtils.throwError is the shared helper used by endpoint converters/validators to raise OAuth2AuthenticationException with description \"OAuth 2.0 Parameter: <parameterName>\" whenever a required OAuth 2.0 endpoint parameter is missing, malformed, or duplicated. It is used across token/device endpoints (e.g. during DPoP parameter validation in validateAndAddDPoPParametersIfAvailable). The description always names the exact failing parameter.","triggerScenarios":"Called when: a required parameter (grant_type, code, redirect_uri, code_verifier, device_code, etc.) is absent; a parameter value fails format validation (invalid URI, invalid scope); a parameter appears multiple times; or DPoP-related parameters are invalid during validateAndAddDPoPParametersIfAvailable.","commonSituations":"Token requests missing code_verifier for a PKCE flow; duplicated query/form parameters from a client library appending params twice; malformed redirect_uri in the token exchange; device authorization grant posts missing device_code; DPoP headers/parameters rejected because they are invalid.","solutions":["Parse the description after \"OAuth 2.0 Parameter:\" to identify the exact parameter and correct it in the request.","Ensure every parameter required by the grant type is present exactly once (grant_type, code, redirect_uri, code_verifier for PKCE, device_code for device grant).","Check the client library is not duplicating parameters (inspect the raw request body/URL).","For DPoP, ensure the DPoP proof JWT and related parameters are well-formed and use the correct algorithm."],"exampleFix":"// before: token request missing PKCE verifier\nPOST /oauth2/token\ngrant_type=authorization_code&code=abc&redirect_uri=...\n// after\nPOST /oauth2/token\ngrant_type=authorization_code&code=abc&redirect_uri=...&client_id=my-client&code_verifier=PLAINTEXT_VERIFIER","handlingStrategy":"validation","validationCode":"function validateTokenRequest(params, grantType) {\n  const required = { 'authorization_code': ['grant_type','code','redirect_uri'],\n                     'urn:ietf:params:oauth:grant-type:device_code': ['grant_type','device_code'] };\n  const need = required[grantType] || ['grant_type'];\n  return need.filter(k => !params.get(k) || params.getAll(k).length > 1);\n}\nconst missingOrDup = validateTokenRequest(tokenParams, grantType);\nif (missingOrDup.length) throw new Error('Bad token request params: ' + missingOrDup.join(','));","typeGuard":"function hasExactlyOnce(params, key) {\n  const all = params.getAll(key);\n  return all.length === 1 && all[0].length > 0;\n}","tryCatchPattern":"try {\n  tokenResponse = requestToken(tokenEndpoint, params);\n} catch (OAuth2AuthenticationException e) {\n  OAuth2Error err = e.getError();\n  if (err.getDescription().startsWith(\"OAuth 2.0 Parameter:\")) {\n    String param = err.getDescription().substring(\"OAuth 2.0 Parameter:\".length()).trim();\n    logger.warn(\"Token request rejected, fix parameter: {}\", param);\n  }\n}","preventionTips":["Send each OAuth parameter exactly once — inspect the raw body for duplicated keys.","Include code_verifier on PKCE authorization_code token requests.","Match redirect_uri exactly to the one used in the authorization request.","When using DPoP, verify proof JWT header/algorithm configuration before calling the endpoint."],"tags":["oauth2","endpoint-validation","parameter-validation","spring-security"],"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-14T11:17:12.474Z"}