spring-projects/spring-security · error · OAuth2AuthenticationException

invalid_token

invalid_token

Error message

Bearer token is malformed

What it means

This error is thrown by DefaultBearerTokenResolver when the Authorization header starts with 'Bearer ' but the remainder does not match the expected token pattern (a single non-whitespace token). The resolver treats any structurally invalid bearer credentials as an OAuth2AuthenticationException carrying the invalid_token error code, per RFC 6750. It signals that the client sent credentials the framework cannot even parse, before any token validation occurs.

Source

Thrown at oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java:100

		if (accessToken != null && accessToken.isBlank()) {
			BearerTokenError error = BearerTokenErrors
				.invalidRequest("The requested token parameter is an empty string");
			throw new OAuth2AuthenticationException(error);
		}

		return accessToken;
	}

	private @Nullable String resolveFromAuthorizationHeader(HttpServletRequest request) {
		String authorization = request.getHeader(this.bearerTokenHeaderName);
		if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
			return null;
		}

		Matcher matcher = authorizationPattern.matcher(authorization);
		if (!matcher.matches()) {
			BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
			throw new OAuth2AuthenticationException(error);
		}

		return matcher.group("token");
	}

	private @Nullable String resolveAccessTokenFromQueryString(HttpServletRequest request) {
		if (!this.allowUriQueryParameter || !HttpMethod.GET.name().equals(request.getMethod())) {
			return null;
		}

		return resolveToken(request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME));
	}

	private @Nullable String resolveAccessTokenFromBody(HttpServletRequest request) {
		if (!this.allowFormEncodedBodyParameter
				|| !MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType())
				|| HttpMethod.GET.name().equals(request.getMethod())) {
			return null;

View on GitHub (pinned to 96852e8860)

Solutions

  1. Inspect the raw Authorization header and remove any whitespace/newlines inside or after the token value
  2. Ensure the client sends exactly 'Authorization: Bearer <single-token>' with no extra spaces
  3. Regenerate the token — some issuers emit tokens containing characters the resolver's pattern rejects
  4. If you need custom schemes, supply a custom BearerTokenResolver instead of the default

Example fix

// before
httpHeaders.set("Authorization", "Bearer " + token + " ");
// after
httpHeaders.set("Authorization", "Bearer " + token.trim());
Defensive patterns

Strategy: validation

Validate before calling

String auth = request.getHeader("Authorization");
if (auth != null && auth.startsWith("Bearer ")) {
    String token = auth.substring(7).trim();
    if (token.isEmpty() || token.matches(".*\\s.*")) {
        throw new IllegalArgumentException("Malformed bearer token");
    }
}

Type guard

boolean isValidBearerHeader(String header) {
    return header != null && header.matches("^Bearer [!-~]+$");
}

Try / catch

try {
    chain.doFilter(request, response);
} catch (OAuth2AuthenticationException e) {
    if ("invalid_token".equals(e.getError().getErrorCode())) {
        response.setStatus(401);
        response.setHeader("WWW-Authenticate", "Bearer error=\"invalid_token\"");
    }
}

Prevention

When it happens

Trigger: Sending an Authorization header with a Bearer scheme whose value contains whitespace (e.g. a pasted token with a trailing newline or internal space), two tokens separated by a space, or an empty value after 'Bearer '. Also triggered by case/format variations that pass the prefix check but fail BearerTokenAuthenticationMatcher's regex, such as 'Bearer a b'.

Common situations: Tokens copied from logs or docs with wrapping whitespace; proxies or gateways mangling the header; misconfigured clients concatenating token type and value twice ('Bearer Bearer abc'); headers that include a newline from environment variable interpolation.

Understand the failure class

Related errors


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