From 4c6fef82b9b8d2a985305bcd1c0d59cc60245583 Mon Sep 17 00:00:00 2001 From: Hyeongi Jeong <jacknie8407@gmail.com> Date: Tue, 15 Oct 2024 16:21:01 +0900 Subject: [PATCH] Fix error when Bearer token is requested with empty string Issue gh-15885 --- .../web/DefaultBearerTokenResolver.java | 5 +++ ...verBearerTokenAuthenticationConverter.java | 5 +++ .../web/DefaultBearerTokenResolverTests.java | 34 +++++++++++++++++++ ...arerTokenAuthenticationConverterTests.java | 4 +-- 4 files changed, 46 insertions(+), 2 deletions(-) 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 da357ca9c9..1d61e11b0f 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 @@ -64,6 +64,11 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver { return authorizationHeaderToken; } if (parameterToken != null && isParameterTokenEnabledForRequest(request)) { + if (!StringUtils.hasText(parameterToken)) { + final BearerTokenError error = BearerTokenErrors + .invalidRequest("The requested token parameter is an empty string"); + throw new OAuth2AuthenticationException(error); + } return parameterToken; } return null; diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverter.java index d30cd8e05a..4f8d33c6d0 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverter.java @@ -78,6 +78,11 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic return authorizationHeaderToken; } if (parameterToken != null && isParameterTokenSupportedForRequest(request)) { + if (!StringUtils.hasText(parameterToken)) { + final BearerTokenError error = BearerTokenErrors + .invalidRequest("The requested token parameter is an empty string"); + throw new OAuth2AuthenticationException(error); + } return parameterToken; } return null; 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 e5cfca01c3..7937a699fd 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 @@ -21,8 +21,11 @@ import java.util.Base64; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.server.resource.BearerTokenError; +import org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -258,4 +261,35 @@ public class DefaultBearerTokenResolverTests { assertThat(this.resolver.resolve(request)).isNull(); } + @Test + public void resolveWhenQueryParameterIsPresentAndEmptyStringThenTokenIsNotResolved() { + this.resolver.setAllowUriQueryParameter(true); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("GET"); + request.addParameter("access_token", ""); + assertThatExceptionOfType(OAuth2AuthenticationException.class).isThrownBy(() -> this.resolver.resolve(request)) + .withMessageContaining("The requested token parameter is an empty string") + .satisfies((e) -> { + BearerTokenError error = (BearerTokenError) e.getError(); + assertThat(error.getErrorCode()).isEqualTo(BearerTokenErrorCodes.INVALID_REQUEST); + assertThat(error.getHttpStatus()).isEqualTo(HttpStatus.BAD_REQUEST); + }); + } + + @Test + public void resolveWhenFormParameterIsPresentAndEmptyStringThenTokenIsNotResolved() { + this.resolver.setAllowFormEncodedBodyParameter(true); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.setContentType("application/x-www-form-urlencoded"); + request.addParameter("access_token", ""); + assertThatExceptionOfType(OAuth2AuthenticationException.class).isThrownBy(() -> this.resolver.resolve(request)) + .withMessageContaining("The requested token parameter is an empty string") + .satisfies((e) -> { + BearerTokenError error = (BearerTokenError) e.getError(); + assertThat(error.getErrorCode()).isEqualTo(BearerTokenErrorCodes.INVALID_REQUEST); + assertThat(error.getHttpStatus()).isEqualTo(HttpStatus.BAD_REQUEST); + }); + } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverterTests.java index 6d9c7a5b98..b43329fc97 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/authentication/ServerBearerTokenAuthenticationConverterTests.java @@ -187,9 +187,9 @@ public class ServerBearerTokenAuthenticationConverterTests { .isThrownBy(() -> convertToToken(request)) .satisfies((ex) -> { BearerTokenError error = (BearerTokenError) ex.getError(); - assertThat(error.getErrorCode()).isEqualTo(BearerTokenErrorCodes.INVALID_TOKEN); + assertThat(error.getErrorCode()).isEqualTo(BearerTokenErrorCodes.INVALID_REQUEST); assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1"); - assertThat(error.getHttpStatus()).isEqualTo(HttpStatus.UNAUTHORIZED); + assertThat(error.getHttpStatus()).isEqualTo(HttpStatus.BAD_REQUEST); }); // @formatter:on }