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
This commit is contained in:
Darren Forsythe 2021-08-08 22:12:12 +01:00 committed by Josh Cummings
parent 770c57ecc9
commit 5556b821e3
2 changed files with 34 additions and 3 deletions

View File

@ -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<String> 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}.

View File

@ -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());
}