Skip to content

Commit aac8544

Browse files
rwinchjzheaux
authored andcommitted
ServerBearerTokenAuthenticationConverter Handles Empty Tokens
Previously ServerBearerTokenAuthenticationConverter would throw an IllegalArgumentException when the access token in a URI was empty String. It also incorrectly provided HttpStatus.BAD_REQUEST for an empty String access token in the headers. This changes ServerBearerTokenAuthenticationConverter to consistently throw a OAuth2AuthenticationException with an HttpStatus.UNAUTHORIZED Fixes gh-7011
1 parent b0597f4 commit aac8544

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java

+17-7
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ public class ServerBearerTokenAuthenticationConverter
4848
private boolean allowUriQueryParameter = false;
4949

5050
public Mono<Authentication> convert(ServerWebExchange exchange) {
51-
return Mono.justOrEmpty(this.token(exchange.getRequest()))
52-
.map(BearerTokenAuthenticationToken::new);
51+
return Mono.justOrEmpty(token(exchange.getRequest()))
52+
.map(token -> {
53+
if (token.isEmpty()) {
54+
BearerTokenError error = invalidTokenError();
55+
throw new OAuth2AuthenticationException(error);
56+
}
57+
return new BearerTokenAuthenticationToken(token);
58+
});
5359
}
5460

5561
private String token(ServerHttpRequest request) {
@@ -88,11 +94,8 @@ private static String resolveFromAuthorizationHeader(HttpHeaders headers) {
8894
if (StringUtils.hasText(authorization) && authorization.startsWith("Bearer")) {
8995
Matcher matcher = authorizationPattern.matcher(authorization);
9096

91-
if ( !matcher.matches() ) {
92-
BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN,
93-
HttpStatus.BAD_REQUEST,
94-
"Bearer token is malformed",
95-
"https://tools.ietf.org/html/rfc6750#section-3.1");
97+
if (!matcher.matches() ) {
98+
BearerTokenError error = invalidTokenError();
9699
throw new OAuth2AuthenticationException(error);
97100
}
98101

@@ -101,6 +104,13 @@ private static String resolveFromAuthorizationHeader(HttpHeaders headers) {
101104
return null;
102105
}
103106

107+
private static BearerTokenError invalidTokenError() {
108+
return new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN,
109+
HttpStatus.UNAUTHORIZED,
110+
"Bearer token is malformed",
111+
"https://tools.ietf.org/html/rfc6750#section-3.1");
112+
}
113+
104114
private boolean isParameterTokenSupportedForRequest(ServerHttpRequest request) {
105115
return this.allowUriQueryParameter && HttpMethod.GET.equals(request.getMethod());
106116
}

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java

+36
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@
1919
import org.junit.Before;
2020
import org.junit.Test;
2121
import org.springframework.http.HttpHeaders;
22+
import org.springframework.http.HttpStatus;
2223
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
2324
import org.springframework.mock.web.server.MockServerWebExchange;
2425
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2526
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
27+
import org.springframework.security.oauth2.server.resource.BearerTokenError;
28+
import org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes;
2629

2730
import java.util.Base64;
2831

2932
import static org.assertj.core.api.Assertions.assertThat;
3033
import static org.assertj.core.api.Assertions.assertThatCode;
34+
import static org.assertj.core.api.Assertions.catchThrowableOfType;
3135

3236
/**
3337
* @author Rob Winch
@@ -52,6 +56,21 @@ public void resolveWhenValidHeaderIsPresentThenTokenIsResolved() {
5256
assertThat(convertToToken(request).getToken()).isEqualTo(TEST_TOKEN);
5357
}
5458

59+
// gh-7011
60+
@Test
61+
public void resolveWhenValidHeaderIsEmptyStringThenTokenIsResolved() {
62+
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest
63+
.get("/")
64+
.header(HttpHeaders.AUTHORIZATION, "Bearer ");
65+
66+
OAuth2AuthenticationException expected = catchThrowableOfType(() -> convertToToken(request),
67+
OAuth2AuthenticationException.class);
68+
BearerTokenError error = (BearerTokenError) expected.getError();
69+
assertThat(error.getErrorCode()).isEqualTo(BearerTokenErrorCodes.INVALID_TOKEN);
70+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
71+
assertThat(error.getHttpStatus()).isEqualTo(HttpStatus.UNAUTHORIZED);
72+
}
73+
5574
@Test
5675
public void resolveWhenNoHeaderIsPresentThenTokenIsNotResolved() {
5776
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest
@@ -114,6 +133,23 @@ public void resolveWhenQueryParameterIsPresentAndSupportedThenTokenIsResolved()
114133
assertThat(convertToToken(request).getToken()).isEqualTo(TEST_TOKEN);
115134
}
116135

136+
// gh-7011
137+
@Test
138+
public void resolveWhenQueryParameterIsEmptyAndSupportedThenOAuth2AuthenticationException() {
139+
this.converter.setAllowUriQueryParameter(true);
140+
141+
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest
142+
.get("/")
143+
.queryParam("access_token", "");
144+
145+
OAuth2AuthenticationException expected = catchThrowableOfType(() -> convertToToken(request),
146+
OAuth2AuthenticationException.class);
147+
BearerTokenError error = (BearerTokenError) expected.getError();
148+
assertThat(error.getErrorCode()).isEqualTo(BearerTokenErrorCodes.INVALID_TOKEN);
149+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
150+
assertThat(error.getHttpStatus()).isEqualTo(HttpStatus.UNAUTHORIZED);
151+
}
152+
117153
@Test
118154
public void resolveWhenQueryParameterIsPresentAndNotSupportedThenTokenIsNotResolved() {
119155
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest

0 commit comments

Comments
 (0)