Skip to content

Commit 6f8ec3d

Browse files
vpavicjzheaux
authored andcommitted
Ensure access token isn't resolved from query for form-encoded requests
Closes gh-5668
1 parent 20b0156 commit 6f8ec3d

File tree

2 files changed

+86
-10
lines changed

2 files changed

+86
-10
lines changed

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import jakarta.servlet.http.HttpServletRequest;
2323

2424
import org.springframework.http.HttpHeaders;
25+
import org.springframework.http.HttpMethod;
2526
import org.springframework.http.MediaType;
2627
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2728
import org.springframework.security.oauth2.server.resource.BearerTokenError;
@@ -38,6 +39,8 @@
3839
*/
3940
public final class DefaultBearerTokenResolver implements BearerTokenResolver {
4041

42+
private static final String ACCESS_TOKEN_PARAMETER_NAME = "access_token";
43+
4144
private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?<token>[a-zA-Z0-9-._~+/]+=*)$",
4245
Pattern.CASE_INSENSITIVE);
4346

@@ -115,7 +118,7 @@ private String resolveFromAuthorizationHeader(HttpServletRequest request) {
115118
}
116119

117120
private static String resolveFromRequestParameters(HttpServletRequest request) {
118-
String[] values = request.getParameterValues("access_token");
121+
String[] values = request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME);
119122
if (values == null || values.length == 0) {
120123
return null;
121124
}
@@ -127,15 +130,24 @@ private static String resolveFromRequestParameters(HttpServletRequest request) {
127130
}
128131

129132
private boolean isParameterTokenSupportedForRequest(final HttpServletRequest request) {
130-
return (("POST".equals(request.getMethod())
131-
&& MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType()))
132-
|| "GET".equals(request.getMethod()));
133+
return isFormEncodedRequest(request) || isGetRequest(request);
134+
}
135+
136+
private static boolean isGetRequest(HttpServletRequest request) {
137+
return HttpMethod.GET.name().equals(request.getMethod());
138+
}
139+
140+
private static boolean isFormEncodedRequest(HttpServletRequest request) {
141+
return MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType());
142+
}
143+
144+
private static boolean hasAccessTokenInQueryString(HttpServletRequest request) {
145+
return (request.getQueryString() != null) && request.getQueryString().contains(ACCESS_TOKEN_PARAMETER_NAME);
133146
}
134147

135-
private boolean isParameterTokenEnabledForRequest(final HttpServletRequest request) {
136-
return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod())
137-
&& MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType()))
138-
|| (this.allowUriQueryParameter && "GET".equals(request.getMethod())));
148+
private boolean isParameterTokenEnabledForRequest(HttpServletRequest request) {
149+
return ((this.allowFormEncodedBodyParameter && isFormEncodedRequest(request) && !isGetRequest(request)
150+
&& !hasAccessTokenInQueryString(request)) || (this.allowUriQueryParameter && isGetRequest(request)));
139151
}
140152

141153
}

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthent
121121
MockHttpServletRequest request = new MockHttpServletRequest();
122122
request.addHeader("Authorization", "Bearer " + TEST_TOKEN);
123123
request.setMethod("GET");
124+
request.setQueryString("access_token=" + TEST_TOKEN);
124125
request.addParameter("access_token", TEST_TOKEN);
125126
assertThatExceptionOfType(OAuth2AuthenticationException.class).isThrownBy(() -> this.resolver.resolve(request))
126127
.withMessageContaining("Found multiple bearer tokens in the request");
@@ -159,7 +160,7 @@ public void resolveWhenParameterIsPresentInMultipartRequestAndFormParameterSuppo
159160
}
160161

161162
@Test
162-
public void resolveWhenFormParameterIsPresentAndSupportedThenTokenIsResolved() {
163+
public void resolveWhenPostAndFormParameterIsPresentAndSupportedThenTokenIsResolved() {
163164
this.resolver.setAllowFormEncodedBodyParameter(true);
164165
MockHttpServletRequest request = new MockHttpServletRequest();
165166
request.setMethod("POST");
@@ -168,6 +169,67 @@ public void resolveWhenFormParameterIsPresentAndSupportedThenTokenIsResolved() {
168169
assertThat(this.resolver.resolve(request)).isEqualTo(TEST_TOKEN);
169170
}
170171

172+
@Test
173+
public void resolveWhenPutAndFormParameterIsPresentAndSupportedThenTokenIsResolved() {
174+
this.resolver.setAllowFormEncodedBodyParameter(true);
175+
176+
MockHttpServletRequest request = new MockHttpServletRequest();
177+
request.setMethod("PUT");
178+
request.setContentType("application/x-www-form-urlencoded");
179+
request.addParameter("access_token", TEST_TOKEN);
180+
181+
assertThat(this.resolver.resolve(request)).isEqualTo(TEST_TOKEN);
182+
}
183+
184+
@Test
185+
public void resolveWhenPatchAndFormParameterIsPresentAndSupportedThenTokenIsResolved() {
186+
this.resolver.setAllowFormEncodedBodyParameter(true);
187+
188+
MockHttpServletRequest request = new MockHttpServletRequest();
189+
request.setMethod("PATCH");
190+
request.setContentType("application/x-www-form-urlencoded");
191+
request.addParameter("access_token", TEST_TOKEN);
192+
193+
assertThat(this.resolver.resolve(request)).isEqualTo(TEST_TOKEN);
194+
}
195+
196+
@Test
197+
public void resolveWhenDeleteAndFormParameterIsPresentAndSupportedThenTokenIsResolved() {
198+
this.resolver.setAllowFormEncodedBodyParameter(true);
199+
200+
MockHttpServletRequest request = new MockHttpServletRequest();
201+
request.setMethod("DELETE");
202+
request.setContentType("application/x-www-form-urlencoded");
203+
request.addParameter("access_token", TEST_TOKEN);
204+
205+
assertThat(this.resolver.resolve(request)).isEqualTo(TEST_TOKEN);
206+
}
207+
208+
@Test
209+
public void resolveWhenGetAndFormParameterIsPresentAndSupportedThenTokenIsNotResolved() {
210+
this.resolver.setAllowFormEncodedBodyParameter(true);
211+
212+
MockHttpServletRequest request = new MockHttpServletRequest();
213+
request.setMethod("GET");
214+
request.setContentType("application/x-www-form-urlencoded");
215+
request.addParameter("access_token", TEST_TOKEN);
216+
217+
assertThat(this.resolver.resolve(request)).isNull();
218+
}
219+
220+
@Test
221+
public void resolveWhenPostAndFormParameterIsSupportedAndQueryParameterIsPresentThenTokenIsNotResolved() {
222+
this.resolver.setAllowFormEncodedBodyParameter(true);
223+
224+
MockHttpServletRequest request = new MockHttpServletRequest();
225+
request.setMethod("POST");
226+
request.setContentType("application/x-www-form-urlencoded");
227+
request.setQueryString("access_token=" + TEST_TOKEN);
228+
request.addParameter("access_token", TEST_TOKEN);
229+
230+
assertThat(this.resolver.resolve(request)).isNull();
231+
}
232+
171233
@Test
172234
public void resolveWhenFormParameterIsPresentAndNotSupportedThenTokenIsNotResolved() {
173235
MockHttpServletRequest request = new MockHttpServletRequest();
@@ -182,6 +244,7 @@ public void resolveWhenQueryParameterIsPresentAndSupportedThenTokenIsResolved()
182244
this.resolver.setAllowUriQueryParameter(true);
183245
MockHttpServletRequest request = new MockHttpServletRequest();
184246
request.setMethod("GET");
247+
request.setQueryString("access_token=" + TEST_TOKEN);
185248
request.addParameter("access_token", TEST_TOKEN);
186249
assertThat(this.resolver.resolve(request)).isEqualTo(TEST_TOKEN);
187250
}
@@ -190,6 +253,7 @@ public void resolveWhenQueryParameterIsPresentAndSupportedThenTokenIsResolved()
190253
public void resolveWhenQueryParameterIsPresentAndNotSupportedThenTokenIsNotResolved() {
191254
MockHttpServletRequest request = new MockHttpServletRequest();
192255
request.setMethod("GET");
256+
request.setQueryString("access_token=" + TEST_TOKEN);
193257
request.addParameter("access_token", TEST_TOKEN);
194258
assertThat(this.resolver.resolve(request)).isNull();
195259
}

0 commit comments

Comments
 (0)