spring-projects/spring-security · error · OAuth2AuthenticationException
invalid_request
invalid_request
Error message
invalid_request
What it means
Thrown by ClientSecretPostAuthenticationConverter.convert() when the client_id form parameter is present but was supplied more than once (or zero times despite clientId being detected). RFC 6749 requires each parameter exactly once, so a duplicate client_id in the token request body is rejected as invalid_request.
Source
Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/ClientSecretPostAuthenticationConverter.java:63
* @see OAuth2ClientAuthenticationFilter
* @see <a target="_blank" href=
* "https://tools.ietf.org/html/rfc6749#section-2.3.1">Section 2.3.1 Client Password</a>
*/
public final class ClientSecretPostAuthenticationConverter implements AuthenticationConverter {
@Override
public @Nullable Authentication convert(HttpServletRequest request) {
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getFormParameters(request);
// client_id (REQUIRED)
String clientId = parameters.getFirst(OAuth2ParameterNames.CLIENT_ID);
if (!StringUtils.hasText(clientId)) {
return null;
}
List<String> clientIdParams = parameters.get(OAuth2ParameterNames.CLIENT_ID);
if (clientIdParams == null || clientIdParams.size() != 1) {
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
}
// client_secret (REQUIRED)
String clientSecret = parameters.getFirst(OAuth2ParameterNames.CLIENT_SECRET);
if (!StringUtils.hasText(clientSecret)) {
return null;
}
List<String> clientSecretParams = parameters.get(OAuth2ParameterNames.CLIENT_SECRET);
if (clientSecretParams == null || clientSecretParams.size() != 1) {
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
}
Map<String, Object> additionalParameters = OAuth2EndpointUtils
.getParametersIfMatchesAuthorizationCodeGrantRequest(request, OAuth2ParameterNames.CLIENT_ID,
OAuth2ParameterNames.CLIENT_SECRET);
return new OAuth2ClientAuthenticationToken(clientId, ClientAuthenticationMethod.CLIENT_SECRET_POST,View on GitHub (pinned to 96852e8860)
Solutions
- Send client_id exactly once in the request body; remove duplicate form fields.
- Remove client_id from the query string if it is already in the POST body.
- Review client code for double-adding the parameter when building the MultiValueMap.
- Log the outgoing form body before the request to confirm a single client_id entry.
Example fix
// before
form.add("client_id", clientId);
form.add("client_id", clientId); // duplicate
// after
form.set("client_id", clientId); // or add exactly once Defensive patterns
Strategy: validation
Validate before calling
MultiValueMap<String, String> dedupe(MultiValueMap<String, String> form) {
LinkedMultiValueMap<String, String> out = new LinkedMultiValueMap<>();
form.forEach((k, v) -> out.set(k, v.get(v.size() - 1)));
return out;
} Try / catch
try { tokenResponse = rest.post().body(form).retrieve().toEntity(...); }
catch (HttpClientErrorException e) {
if (e.getResponseBodyAsString().contains("invalid_request")) { log.error("Check for duplicate client_id in body/query"); }
throw e;
} Prevention
- Use map.set() instead of add() for singleton OAuth2 parameters.
- Never place client_id in both query string and form body.
When it happens
Trigger: POSTing a token request whose body contains client_id twice, e.g. both in a query string merged into parameters and in the form body, or repeated form fields.
Common situations: Client libraries appending client_id to the URL while also including it in the form body; form builders that add the field twice; combining Spring's default parameter handling with manually added parameters.
Related errors
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/a56127fd37acdcc8.
Report an issue: GitHub.