spring-projects/spring-security · error · OAuth2AuthenticationException

unsupported_grant_type

unsupported_grant_type

Error message

OAuth 2.0 Parameter: grant_type

What it means

After grant_type passes the single-value check, OAuth2TokenEndpointFilter asks the configured AuthenticationConverter to build a grant authentication. If no converter recognizes the grant_type, the filter throws an OAuth2AuthenticationException with error code 'unsupported_grant_type', which maps to an HTTP 400 'unsupported_grant_type' response as defined by OAuth 2.0.

Solutions

  1. Enable/registers support for the requested grant type (e.g. add OAuth2ClientCredentialsAuthenticationProvider or the token-exchange dependencies) in the authorization server security config
  2. Correct the grant_type spelling on the client (e.g. authorization_code, refresh_token, client_credentials)
  3. Check the Spring Security OAuth2 Authorization Server version supports the requested grant

Example fix

// before: server only allows authorization_code
http.oauth2AuthorizationServer(authorizationServer -> authorizationServer.tokenEndpoint(t -> t.accessTokenRequestConverter(new OAuth2AuthorizationCodeAuthenticationConverter(...))))
// after: also support client_credentials
http.oauth2AuthorizationServer(authorizationServer -> authorizationServer
    .tokenEndpoint(t -> t.accessTokenRequestConverters(c -> c.add(new OAuth2ClientCredentialsAuthenticationConverter()))))
Defensive patterns

Strategy: try-catch

Validate before calling

Set<String> supported = Set.of("authorization_code","refresh_token","client_credentials","urn:ietf:params:oauth:grant-type:device_code");
if (!supported.contains(grantType)) {
    throw new IllegalArgumentException("grant_type not enabled on this server: " + grantType);
}

Try / catch

try {
    TokenResponse r = client.tokenRequest(...);
} catch (OAuth2ErrorResponseException ex) {
    if ("unsupported_grant_type".equals(ex.getError().getErrorCode())) {
        // fall back to a supported grant or surface a config error
    }
}

Prevention

When it happens

Trigger: Requesting the token endpoint with a grant_type not enabled on the authorization server, e.g. 'password', 'client_credentials' when disabled, 'urn:ietf:params:oauth:grant-type:token-exchange' without the corresponding dependency/converter, or a typo like 'authorizationCode'.

Common situations: Authorization server not configured with the grant (e.g. missing OAuth2TokenExchangeAuthenticationProvider/converter), Spring Security version where a grant type is not yet supported, or client requesting a grant the server intentionally restricts.

Related errors


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

Appendix: source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilter.java:163

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		if (!this.tokenEndpointMatcher.matches(request)) {
			filterChain.doFilter(request, response);
			return;
		}

		try {
			String[] grantTypes = request.getParameterValues(OAuth2ParameterNames.GRANT_TYPE);
			if (grantTypes == null || grantTypes.length != 1) {
				throw createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.GRANT_TYPE);
			}

			Authentication authorizationGrantAuthentication = this.authenticationConverter.convert(request);
			if (authorizationGrantAuthentication == null) {
				throw createException(OAuth2ErrorCodes.UNSUPPORTED_GRANT_TYPE, OAuth2ParameterNames.GRANT_TYPE);
			}
			if (authorizationGrantAuthentication instanceof AbstractAuthenticationToken authenticationToken) {
				authenticationToken.setDetails(this.authenticationDetailsSource.buildDetails(request));
			}

			OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = (OAuth2AccessTokenAuthenticationToken) this.authenticationManager
				.authenticate(authorizationGrantAuthentication);
			this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, accessTokenAuthentication);
		}
		catch (OAuth2AuthenticationException ex) {
			SecurityContextHolder.clearContext();
			if (this.logger.isTraceEnabled()) {
				this.logger.trace(LogMessage.format("Token request failed: %s", ex.getError()), ex);
			}
			this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
		}
	}

View on GitHub (pinned to 96852e8860)