Skip to content

OAuth2 Basic authentication decodes credentials twice causing ‘+’ to become space #18934

@assassion2

Description

@assassion2

Describe the bug

In the OAuth2 client authentication flow using HTTP Basic authentication, client credentials are Base64-decoded and then additionally passed through URLDecoder.decode().
ClientSecretBasicAuthenticationConverter.java

This results in incorrect handling of + characters in client secrets because URLDecoder follows application/x-www-form-urlencoded rules and converts + into a space.

As a result, valid client credentials containing + fail authentication.

This behavior appears to violate RFC 7617 (HTTP Basic Authentication), which specifies that credentials are raw strings encoded using Base64 and should not be URL-decoded.

To Reproduce
1. Register an OAuth2 client with a secret containing a + character, for example:
client-id: test-client
client-secret: abc+123
2. Send a token request using HTTP Basic authentication:
Authorization: Basic base64(test-client:abc+123)
3. Observe authentication failure due to credential mismatch.
Expected behavior

After Base64 decoding, the client credentials should be used as-is.

URLDecoder.decode() should not be applied when processing HTTP Basic authentication credentials.

Credentials containing + or percent-encoded characters should remain unchanged after Base64 decoding.

Minimal reproduction example:
String raw = "test-client:abc+123";
String encoded = Base64.getEncoder().encodeToString(raw.getBytes(StandardCharsets.UTF_8));

String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);

// current behavior (problematic)
String secret = URLDecoder.decode(decoded.split(":", 2)[1], StandardCharsets.UTF_8.name());

// expected behavior
String expectedSecret = decoded.split(":", 2)[1];

Authentication succeeds only when URL decoding is removed.

Metadata

Metadata

Assignees

Labels

in: oauth2An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)status: duplicateA duplicate of another issue

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions