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:
parent
770c57ecc9
commit
5556b821e3
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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;
|
package org.springframework.security.oauth2.server.resource.web.server;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
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.BearerTokenError;
|
||||||
import org.springframework.security.oauth2.server.resource.BearerTokenErrors;
|
import org.springframework.security.oauth2.server.resource.BearerTokenErrors;
|
||||||
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
|
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
|
@ -65,7 +67,8 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic
|
||||||
|
|
||||||
private String token(ServerHttpRequest request) {
|
private String token(ServerHttpRequest request) {
|
||||||
String authorizationHeaderToken = resolveFromAuthorizationHeader(request.getHeaders());
|
String authorizationHeaderToken = resolveFromAuthorizationHeader(request.getHeaders());
|
||||||
String parameterToken = request.getQueryParams().getFirst("access_token");
|
String parameterToken = resolveAccessTokenFromRequest(request);
|
||||||
|
|
||||||
if (authorizationHeaderToken != null) {
|
if (authorizationHeaderToken != null) {
|
||||||
if (parameterToken != null) {
|
if (parameterToken != null) {
|
||||||
BearerTokenError error = BearerTokenErrors
|
BearerTokenError error = BearerTokenErrors
|
||||||
|
|
@ -80,6 +83,20 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic
|
||||||
return null;
|
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
|
* Set if transport of access token using URI query parameter is supported. Defaults
|
||||||
* to {@code false}.
|
* to {@code false}.
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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();
|
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) {
|
private BearerTokenAuthenticationToken convertToToken(MockServerHttpRequest.BaseBuilder<?> request) {
|
||||||
return convertToToken(request.build());
|
return convertToToken(request.build());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue