spring-projects/spring-security · error · OAuth2AuthenticationException

OAuth 2.0 Token Revocation Parameter: ${parameterName}

Error message

OAuth 2.0 Token Revocation Parameter: ${parameterName}

What it means

The OAuth2TokenRevocationAuthenticationConverter throws this when a Token Revocation request violates RFC 7009 section 2.1: the required 'token' parameter is missing or duplicated, or 'token_type_hint' is supplied more than once. The message embeds the offending parameterName. It is thrown as an OAuth2AuthenticationException from convert() and rendered as a standard OAuth2 error response.

Source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenRevocationAuthenticationConverter.java:79

		Assert.notNull(token, "token cannot be null");

		// token_type_hint (OPTIONAL)
		String tokenTypeHint = parameters.getFirst(OAuth2ParameterNames.TOKEN_TYPE_HINT);
		List<String> tokenTypeHintParams = parameters.get(OAuth2ParameterNames.TOKEN_TYPE_HINT);
		if (StringUtils.hasText(tokenTypeHint) && tokenTypeHintParams != null && tokenTypeHintParams.size() != 1) {
			throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN_TYPE_HINT);
		}

		Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
		Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");

		return new OAuth2TokenRevocationAuthenticationToken(token, clientPrincipal, tokenTypeHint);
	}

	private static void throwError(String errorCode, String parameterName) {
		OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Token Revocation Parameter: " + parameterName,
				"https://datatracker.ietf.org/doc/html/rfc7009#section-2.1");
		throw new OAuth2AuthenticationException(error);
	}

}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Send exactly one non-empty 'token' form parameter in the revocation POST body.
  2. If using token_type_hint, send it at most once with value access_token or refresh_token.
  3. Check the error detail for parameterName and log the outgoing request body to find duplicates or omissions.
  4. Verify no intermediate proxy duplicates form fields.

Example fix

// before
await fetch('/oauth2/revoke', { method: 'POST', body: 'token=&token=' }); // empty + duplicate
// after
await fetch('/oauth2/revoke', { method: 'POST', body: 'token=' + encodeURIComponent(token) });
Defensive patterns

Strategy: validation

Validate before calling

const params = new URLSearchParams(body);
if (params.getAll('token').length !== 1 || !params.get('token')) {
  throw new Error('revocation requires exactly one non-empty token parameter');
}

Type guard

function isRevocationBody(body) {
  const p = body instanceof URLSearchParams ? body : new URLSearchParams(body);
  return p.getAll('token').length === 1 && p.get('token').length > 0;
}

Try / catch

try {
  await fetch('/oauth2/revoke', { method: 'POST', body });
} catch (e) {
  if (e instanceof OAuth2AuthenticationException || e.message.includes('invalid_request')) {
    console.error('Revocation parameter error:', e.message);
  }
}

Prevention

When it happens

Trigger: POST to /oauth2/revoke without the 'token' form parameter, with 'token' repeated, or with a duplicated/missing 'token_type_hint'; throwError is invoked from convert() during parameter validation.

Common situations: Client libraries that drop empty form fields when token is empty string; duplicated parameters after URL/form encoding bugs; gateways that merge query and body parameters causing duplicates; typos like 'tokens=' instead of 'token='.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/36f3f46e7a06b48e. Report an issue: GitHub.