spring-projects/spring-security · error · OAuth2AuthenticationException

invalid_request

invalid_request

Error message

OpenID Connect 1.0 Logout Request Parameter: id_token_hint

What it means

OidcLogoutAuthenticationConverter requires the 'id_token_hint' parameter on the OIDC logout endpoint. Although the OIDC spec marks it RECOMMENDED, this converter treats it as REQUIRED: if the parameter is missing, blank, or supplied more than once, it throws an OAuth2AuthenticationException with error code 'invalid_request' naming 'id_token_hint'.

Source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/authentication/OidcLogoutAuthenticationConverter.java:63

 * @see AuthenticationConverter
 * @see OidcLogoutAuthenticationToken
 * @see OidcLogoutEndpointFilter
 */
public final class OidcLogoutAuthenticationConverter implements AuthenticationConverter {

	private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken("anonymous",
			"anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));

	@Override
	public Authentication convert(HttpServletRequest request) {
		MultiValueMap<String, String> parameters = "GET".equals(request.getMethod())
				? OAuth2EndpointUtils.getQueryParameters(request) : OAuth2EndpointUtils.getFormParameters(request);

		// id_token_hint (REQUIRED) // RECOMMENDED as per spec
		String idTokenHint = parameters.getFirst("id_token_hint");
		List<String> idTokenHintParameters = parameters.get("id_token_hint");
		if (!StringUtils.hasText(idTokenHint) || idTokenHintParameters == null || idTokenHintParameters.size() != 1) {
			throw createException(OAuth2ErrorCodes.INVALID_REQUEST, "id_token_hint");
		}

		Authentication principal = SecurityContextHolder.getContext().getAuthentication();
		if (principal == null) {
			principal = ANONYMOUS_AUTHENTICATION;
		}

		String sessionId = null;
		HttpSession session = request.getSession(false);
		if (session != null) {
			sessionId = session.getId();
		}

		// client_id (OPTIONAL)
		String clientId = parameters.getFirst(OAuth2ParameterNames.CLIENT_ID);
		List<String> clientIdParameters = parameters.get(OAuth2ParameterNames.CLIENT_ID);
		if (StringUtils.hasText(clientId) && (clientIdParameters == null || clientIdParameters.size() != 1)) {
			throw createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.CLIENT_ID);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Always include exactly one non-empty id_token_hint parameter pointing at a valid ID token from the RP session
  2. Remove duplicate hidden form fields so the parameter appears only once
  3. If you cannot supply a hint, use plain session logout instead of the OIDC logout endpoint

Example fix

// before
<a href="/logout">Log out</a>
// after
<a th:href="@{'/logout?id_token_hint=' + ${idToken}}">Log out</a>
Defensive patterns

Strategy: validation

Validate before calling

String hint = request.getParameter("id_token_hint");
if (hint == null || hint.isBlank()) { throw new IllegalArgumentException("id_token_hint is required for OIDC logout"); }

Try / catch

try {
    chain.doFilter(request, response);
} catch (OAuth2AuthenticationException ex) {
    if ("id_token_hint".equals(ex.getError().getUri()) || ex.getMessage().contains("id_token_hint")) {
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, "id_token_hint parameter is required");
    }
}

Prevention

When it happens

Trigger: GET/POST to the logout endpoint (default /logout with OidcLogoutEndpoint configured) without 'id_token_hint', with an empty value, or with duplicate 'id_token_hint' parameters in the query string or form body.

Common situations: Clients implementing RP-initiated logout that omit the hint, HTML forms submitting the parameter twice (e.g. hidden field plus query param), or proxies/redirects mangling the query string.

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/ac4f832a24ddba4d. Report an issue: GitHub.