diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java index 14c3a2558f9..eb457e571a8 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java @@ -39,6 +39,9 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver { private static final Pattern authorizationPattern = Pattern.compile( "^Bearer (?[a-zA-Z0-9-._~+/]+)=*$", Pattern.CASE_INSENSITIVE); + private static final Pattern queryParametersPattern = Pattern.compile( + "^(?[a-zA-Z0-9-._~+/]+)=*$", + Pattern.CASE_INSENSITIVE); private boolean allowFormEncodedBodyParameter = false; @@ -90,17 +93,7 @@ public void setAllowUriQueryParameter(boolean allowUriQueryParameter) { private static String resolveFromAuthorizationHeader(HttpServletRequest request) { String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); if (StringUtils.startsWithIgnoreCase(authorization, "bearer")) { - Matcher matcher = authorizationPattern.matcher(authorization); - - if (!matcher.matches()) { - BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, - HttpStatus.UNAUTHORIZED, - "Bearer token is malformed", - "https://tools.ietf.org/html/rfc6750#section-3.1"); - throw new OAuth2AuthenticationException(error); - } - - return matcher.group("token"); + return validateToken(authorization, authorizationPattern); } return null; } @@ -112,7 +105,7 @@ private static String resolveFromRequestParameters(HttpServletRequest request) { } if (values.length == 1) { - return values[0]; + return validateToken(values[0], queryParametersPattern); } BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, @@ -126,4 +119,18 @@ private boolean isParameterTokenSupportedForRequest(HttpServletRequest request) return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod())) || (this.allowUriQueryParameter && "GET".equals(request.getMethod()))); } + + private static String validateToken(String token, Pattern pattern) { + Matcher matcher = pattern.matcher(token); + + if (!matcher.matches()) { + BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, + HttpStatus.UNAUTHORIZED, + "Bearer token is malformed", + "https://tools.ietf.org/html/rfc6750#section-3.1"); + throw new OAuth2AuthenticationException(error); + } + + return matcher.group("token"); + } } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java index d0487369429..b1f2f8d0453 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java @@ -165,4 +165,28 @@ public void resolveWhenQueryParameterIsPresentAndNotSupportedThenTokenIsNotResol assertThat(this.resolver.resolve(request)).isNull(); } + + @Test + public void resolveWhenQueryParameterIsPresentWithMissingTokenThenAuthenticationExceptionIsThrown() { + this.resolver.setAllowUriQueryParameter(true); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("GET"); + request.addParameter("access_token", ""); + + assertThatCode(() -> this.resolver.resolve(request)).isInstanceOf(OAuth2AuthenticationException.class) + .hasMessageContaining(("Bearer token is malformed")); + } + + @Test + public void resolveWhenQueryParameterWithInvalidCharactersIsPresentThenAuthenticationExceptionIsThrown() { + this.resolver.setAllowUriQueryParameter(true); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("GET"); + request.addParameter("access_token", "an\"invalid\"token"); + + assertThatCode(() -> this.resolver.resolve(request)).isInstanceOf(OAuth2AuthenticationException.class) + .hasMessageContaining(("Bearer token is malformed")); + } }