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

  1. Send client_id exactly once in the request body; remove duplicate form fields.
  2. Remove client_id from the query string if it is already in the POST body.
  3. Review client code for double-adding the parameter when building the MultiValueMap.
  4. 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

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.