From 5556b821e32a57104c54211fb1a1fffb7c1c9456 Mon Sep 17 00:00:00 2001 From: Darren Forsythe Date: Sun, 8 Aug 2021 22:12:12 +0100 Subject: [PATCH] Check for multiple access tokens per rfc 6750 Check for multiple access tokens on the ServerHttpRequest rather than get get first. If multiples are found throw a OAuth2AuthenticationException. Closes gh-5708 --- ...verBearerTokenAuthenticationConverter.java | 21 +++++++++++++++++-- ...arerTokenAuthenticationConverterTests.java | 16 +++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java index e4d3d6dfc9..7ec7f75646 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.security.oauth2.server.resource.web.server; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -30,6 +31,7 @@ import org.springframework.security.oauth2.server.resource.BearerTokenAuthentica import org.springframework.security.oauth2.server.resource.BearerTokenError; import org.springframework.security.oauth2.server.resource.BearerTokenErrors; import org.springframework.security.web.server.authentication.ServerAuthenticationConverter; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; @@ -65,7 +67,8 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic private String token(ServerHttpRequest request) { String authorizationHeaderToken = resolveFromAuthorizationHeader(request.getHeaders()); - String parameterToken = request.getQueryParams().getFirst("access_token"); + String parameterToken = resolveAccessTokenFromRequest(request); + if (authorizationHeaderToken != null) { if (parameterToken != null) { BearerTokenError error = BearerTokenErrors @@ -80,6 +83,20 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic return null; } + private static String resolveAccessTokenFromRequest(ServerHttpRequest request) { + List parameterTokens = request.getQueryParams().get("access_token"); + if (CollectionUtils.isEmpty(parameterTokens)) { + return null; + } + if (parameterTokens.size() == 1) { + return parameterTokens.get(0); + } + + BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request"); + throw new OAuth2AuthenticationException(error); + + } + /** * Set if transport of access token using URI query parameter is supported. Defaults * to {@code false}. diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java index 9a6cb9e2a1..54869061be 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -203,6 +203,20 @@ public class ServerBearerTokenAuthenticationConverterTests { assertThat(convertToToken(request)).isNull(); } + @Test + void resolveWhenQueryParameterHasMultipleAccessTokensThenOAuth2AuthenticationException() { + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").queryParam("access_token", + TEST_TOKEN, TEST_TOKEN); + assertThatExceptionOfType(OAuth2AuthenticationException.class).isThrownBy(() -> convertToToken(request)) + .satisfies((ex) -> { + BearerTokenError error = (BearerTokenError) ex.getError(); + 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.BAD_REQUEST); + }); + + } + private BearerTokenAuthenticationToken convertToToken(MockServerHttpRequest.BaseBuilder request) { return convertToToken(request.build()); }