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
- Base64-encode the credentials on the client: 'Basic ' + base64(username + ':' + password) (e.g. curl -u user:password does this for you).
- Log the raw Authorization header (minus secrets) to confirm what actually reaches the server; fix the client or intermediate proxy that is mangling it.
- If you control the bytes, ensure you use standard Base64 (not URL-safe or mime variants that the strict decoder rejects).
- 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
- Always Base64-encode 'username:password' with a standard encoder before building the Basic header
- Use client libraries (curl -u, RestTemplate basic auth, requests auth=(u,p)) instead of hand-built headers
- Encode UTF-8 explicitly to avoid charset-induced byte corruption
- Integration-test the exact Authorization header bytes your client sends
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- An error occurred while attempting to decode the Jwt…
- Authentication for password change failed.
- Authentication.getCredentials() cannot be null
- Bad credentials
- Bad credentials
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)