Skip to content

Commit ad2f999

Browse files
committed
Polish BasicAuthenticationConverter
This reverts to the old behavior from BasicAuthenticationFilter. Specifically, if a token has an empty password, it still parses a username and an empty String password. Issue gh-7025
1 parent d157125 commit ad2f999

File tree

2 files changed

+31
-25
lines changed

2 files changed

+31
-25
lines changed

web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationConverter.java

+19-25
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717

1818
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
1919

20-
import java.io.UnsupportedEncodingException;
20+
import java.nio.charset.Charset;
2121
import java.nio.charset.StandardCharsets;
2222
import java.util.Base64;
2323

2424
import javax.servlet.http.HttpServletRequest;
2525

2626
import org.springframework.security.authentication.AuthenticationDetailsSource;
2727
import org.springframework.security.authentication.BadCredentialsException;
28-
import org.springframework.security.authentication.InternalAuthenticationServiceException;
2928
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
3029
import org.springframework.security.web.authentication.AuthenticationConverter;
3130
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
@@ -47,7 +46,7 @@ public class BasicAuthenticationConverter implements AuthenticationConverter {
4746

4847
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;
4948

50-
private String credentialsCharset = StandardCharsets.UTF_8.name();
49+
private Charset credentialsCharset = StandardCharsets.UTF_8;
5150

5251
public BasicAuthenticationConverter() {
5352
this(new WebAuthenticationDetailsSource());
@@ -58,16 +57,16 @@ public BasicAuthenticationConverter(
5857
this.authenticationDetailsSource = authenticationDetailsSource;
5958
}
6059

61-
public String getCredentialsCharset() {
62-
return credentialsCharset;
60+
public Charset getCredentialsCharset() {
61+
return this.credentialsCharset;
6362
}
6463

65-
public void setCredentialsCharset(String credentialsCharset) {
64+
public void setCredentialsCharset(Charset credentialsCharset) {
6665
this.credentialsCharset = credentialsCharset;
6766
}
6867

6968
public AuthenticationDetailsSource<HttpServletRequest, ?> getAuthenticationDetailsSource() {
70-
return authenticationDetailsSource;
69+
return this.authenticationDetailsSource;
7170
}
7271

7372
public void setAuthenticationDetailsSource(
@@ -88,34 +87,29 @@ public UsernamePasswordAuthenticationToken convert(HttpServletRequest request) {
8887
return null;
8988
}
9089

91-
byte[] base64Token = header.substring(6).getBytes();
90+
byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
9291
byte[] decoded;
9392
try {
9493
decoded = Base64.getDecoder().decode(base64Token);
95-
} catch (IllegalArgumentException e) {
96-
throw new BadCredentialsException("Failed to decode basic authentication token");
9794
}
98-
99-
String token;
100-
try {
101-
token = new String(decoded, getCredentialsCharset(request));
102-
} catch (UnsupportedEncodingException e) {
103-
throw new InternalAuthenticationServiceException(e.getMessage(), e);
95+
catch (IllegalArgumentException e) {
96+
throw new BadCredentialsException(
97+
"Failed to decode basic authentication token");
10498
}
10599

106-
String[] tokens = token.split(":");
107-
if (tokens.length != 2) {
108-
throw new BadCredentialsException("Invalid basic authentication token");
109-
}
100+
String token = new String(decoded, getCredentialsCharset(request));
110101

111-
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(tokens[0],
112-
tokens[1]);
113-
authentication.setDetails(authenticationDetailsSource.buildDetails(request));
102+
int delim = token.indexOf(":");
114103

115-
return authentication;
104+
if (delim == -1) {
105+
throw new BadCredentialsException("Invalid basic authentication token");
106+
}
107+
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(token.substring(0, delim), token.substring(delim + 1));
108+
result.setDetails(this.authenticationDetailsSource.buildDetails(request));
109+
return result;
116110
}
117111

118-
protected String getCredentialsCharset(HttpServletRequest request) {
112+
protected Charset getCredentialsCharset(HttpServletRequest request) {
119113
return getCredentialsCharset();
120114
}
121115

web/src/test/java/org/springframework/security/web/authentication/www/BasicAuthenticationConverterTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,16 @@ public void testWhenInvalidBase64ThenError() throws Exception {
9999
converter.convert(request);
100100
}
101101

102+
@Test
103+
public void convertWhenEmptyPassword() {
104+
String token = "rod:";
105+
MockHttpServletRequest request = new MockHttpServletRequest();
106+
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
107+
UsernamePasswordAuthenticationToken authentication = converter.convert(request);
108+
109+
verify(authenticationDetailsSource).buildDetails(any());
110+
assertThat(authentication).isNotNull();
111+
assertThat(authentication.getName()).isEqualTo("rod");
112+
assertThat(authentication.getCredentials()).isEqualTo("");
113+
}
102114
}

0 commit comments

Comments
 (0)