spring-projects/spring-security · error · BadCredentialsException

Failed to decode basic authentication token

Error message

Failed to decode basic authentication token

What it means

BasicAuthenticationConverter.decode throws this BadCredentialsException when the credentials portion of the HTTP Basic 'Authorization' header cannot be Base64-decoded. Spring Security treats a malformed Base64 token as invalid credentials rather than a server error, so the request is rejected through the authentication failure path (typically 401).

Solutions

  1. Base64-encode the credentials on the client: 'Basic ' + base64(username + ':' + password) (e.g. curl -u user:password does this for you).
  2. Log the raw Authorization header (minus secrets) to confirm what actually reaches the server; fix the client or intermediate proxy that is mangling it.
  3. If you control the bytes, ensure you use standard Base64 (not URL-safe or mime variants that the strict decoder rejects).
  4. Client-side, catch org.springframework.security.authentication.BadCredentialsException / AuthenticationException and return 401 rather than retrying.

Example fix

// before (client)
connection.setRequestProperty("Authorization", "Basic " + user + ":" + password);
// after
String token = Base64.getEncoder().encodeToString((user + ":" + password).getBytes(StandardCharsets.UTF_8));
connection.setRequestProperty("Authorization", "Basic " + token);
Defensive patterns

Strategy: try-catch

Validate before calling

String creds = header.startsWith("Basic ") ? header.substring(6) : null;
boolean isBase64 = creds != null && creds.matches("[A-Za-z0-9+/=\r\n]+") && creds.length() % 4 == 0;
if (!isBase64) throw new IllegalArgumentException("Authorization credentials are not valid Base64");

Type guard

boolean isValidBase64(String s) {
    try { java.util.Base64.getDecoder().decode(s); return true; }
    catch (IllegalArgumentException e) { return false; }
}

Try / catch

try {
    authResult = filter.doFilter(request, response, chain);
} catch (AuthenticationException e) {
    // BadCredentialsException("Failed to decode basic authentication token")
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Malformed Basic credentials");
}

Prevention

When it happens

Trigger: A request sends an 'Authorization: Basic <token>' header whose credentials segment is not valid Base64 (e.g. raw 'user:password' without Base64 encoding, truncated Base64, or characters outside the Base64 alphabet). Base64.getDecoder().decode(base64Token) throws IllegalArgumentException, which is converted into this exception.

Common situations: Clients hand-building the Authorization header without encoding; curl/scripts sending 'Basic user:password' literally; a proxy or middleware corrupting or truncating the header; tests using plaintext credentials; non-ASCII characters double-encoded incorrectly.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationConverter.java:109

		byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
		byte[] decoded = decode(base64Token);
		String token = new String(decoded, getCredentialsCharset(request));
		int delim = token.indexOf(":");
		if (delim == -1) {
			throw new BadCredentialsException("Invalid basic authentication token");
		}
		UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken
			.unauthenticated(token.substring(0, delim), token.substring(delim + 1));
		result.setDetails(this.authenticationDetailsSource.buildDetails(request));
		return result;
	}

	private byte[] decode(byte[] base64Token) {
		try {
			return Base64.getDecoder().decode(base64Token);
		}
		catch (IllegalArgumentException ex) {
			throw new BadCredentialsException("Failed to decode basic authentication token");
		}
	}

	protected Charset getCredentialsCharset(HttpServletRequest request) {
		return getCredentialsCharset();
	}

}

View on GitHub (pinned to 96852e8860)