Skip to content

Commit 890b1ef

Browse files
martin-lindstromjgrandja
authored andcommitted
Fix to save all values for multi-valued request parameters
Fixes gh-1250
1 parent 4bb741b commit 890b1ef

15 files changed

+53
-19
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AuthorizationCodeAuthenticationConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public Authentication convert(HttpServletRequest request) {
8484
!key.equals(OAuth2ParameterNames.CLIENT_ID) &&
8585
!key.equals(OAuth2ParameterNames.CODE) &&
8686
!key.equals(OAuth2ParameterNames.REDIRECT_URI)) {
87-
additionalParameters.put(key, value.get(0));
87+
additionalParameters.put(key, value.size() == 1 ? value.get(0) : value.toArray(new String[0]));
8888
}
8989
});
9090

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AuthorizationCodeRequestAuthenticationConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public Authentication convert(HttpServletRequest request) {
138138
!key.equals(OAuth2ParameterNames.REDIRECT_URI) &&
139139
!key.equals(OAuth2ParameterNames.SCOPE) &&
140140
!key.equals(OAuth2ParameterNames.STATE)) {
141-
additionalParameters.put(key, value.get(0));
141+
additionalParameters.put(key, value.size() == 1 ? value.get(0) : value.toArray(new String[0]));
142142
}
143143
});
144144

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AuthorizationConsentAuthenticationConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public Authentication convert(HttpServletRequest request) {
9393
if (!key.equals(OAuth2ParameterNames.CLIENT_ID) &&
9494
!key.equals(OAuth2ParameterNames.STATE) &&
9595
!key.equals(OAuth2ParameterNames.SCOPE)) {
96-
additionalParameters.put(key, value.get(0));
96+
additionalParameters.put(key, value.size() == 1 ? value.get(0) : value.toArray(new String[0]));
9797
}
9898
});
9999

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ClientCredentialsAuthenticationConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public Authentication convert(HttpServletRequest request) {
7979
parameters.forEach((key, value) -> {
8080
if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
8181
!key.equals(OAuth2ParameterNames.SCOPE)) {
82-
additionalParameters.put(key, value.get(0));
82+
additionalParameters.put(key, value.size() == 1 ? value.get(0) : value.toArray(new String[0]));
8383
}
8484
});
8585

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2EndpointUtils.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
package org.springframework.security.oauth2.server.authorization.web.authentication;
1717

1818
import java.util.Collections;
19-
import java.util.HashMap;
2019
import java.util.Map;
20+
import java.util.stream.Collectors;
2121

2222
import javax.servlet.http.HttpServletRequest;
2323

@@ -58,11 +58,13 @@ static Map<String, Object> getParametersIfMatchesAuthorizationCodeGrantRequest(H
5858
if (!matchesAuthorizationCodeGrantRequest(request)) {
5959
return Collections.emptyMap();
6060
}
61-
Map<String, Object> parameters = new HashMap<>(getParameters(request).toSingleValueMap());
61+
MultiValueMap<String, String> parameters = getParameters(request);
6262
for (String exclusion : exclusions) {
6363
parameters.remove(exclusion);
6464
}
65-
return parameters;
65+
return parameters.entrySet().stream()
66+
.collect(Collectors.toMap(Map.Entry::getKey,
67+
e -> e.getValue().size() == 1 ? e.getValue().get(0) : e.getValue().toArray(new String[0])));
6668
}
6769

6870
static boolean matchesAuthorizationCodeGrantRequest(HttpServletRequest request) {

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2RefreshTokenAuthenticationConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public Authentication convert(HttpServletRequest request) {
9090
if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
9191
!key.equals(OAuth2ParameterNames.REFRESH_TOKEN) &&
9292
!key.equals(OAuth2ParameterNames.SCOPE)) {
93-
additionalParameters.put(key, value.get(0));
93+
additionalParameters.put(key, value.size() == 1 ? value.get(0) : value.toArray(new String[0]));
9494
}
9595
});
9696

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenIntrospectionAuthenticationConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public Authentication convert(HttpServletRequest request) {
6969
parameters.forEach((key, value) -> {
7070
if (!key.equals(OAuth2ParameterNames.TOKEN) &&
7171
!key.equals(OAuth2ParameterNames.TOKEN_TYPE_HINT)) {
72-
additionalParameters.put(key, value.get(0));
72+
additionalParameters.put(key, value.size() == 1 ? value.get(0) : value.toArray(new String[0]));
7373
}
7474
});
7575

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/PublicClientAuthenticationConverter.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.security.oauth2.server.authorization.web.authentication;
1717

1818
import java.util.HashMap;
19+
import java.util.Map;
1920

2021
import javax.servlet.http.HttpServletRequest;
2122

@@ -68,7 +69,12 @@ public Authentication convert(HttpServletRequest request) {
6869

6970
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
7071

72+
Map<String, Object> additionalParameters = new HashMap<>();
73+
parameters.forEach((key, value) -> {
74+
additionalParameters.put(key, value.size() == 1 ? value.get(0) : value.toArray(new String[0]));
75+
});
76+
7177
return new OAuth2ClientAuthenticationToken(clientId, ClientAuthenticationMethod.NONE, null,
72-
new HashMap<>(parameters.toSingleValueMap()));
78+
additionalParameters);
7379
}
7480
}

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationEndpointFilterTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,8 @@ public void doFilterWhenAuthorizationRequestAuthenticatedThenAuthorizationRespon
556556
.thenReturn(authorizationCodeRequestAuthenticationResult);
557557

558558
MockHttpServletRequest request = createAuthorizationRequest(registeredClient);
559+
request.addParameter("foo", "value1", "value2");
560+
559561
MockHttpServletResponse response = new MockHttpServletResponse();
560562
FilterChain filterChain = mock(FilterChain.class);
561563

@@ -570,6 +572,12 @@ public void doFilterWhenAuthorizationRequestAuthenticatedThenAuthorizationRespon
570572
.asInstanceOf(type(WebAuthenticationDetails.class))
571573
.extracting(WebAuthenticationDetails::getRemoteAddress)
572574
.isEqualTo(REMOTE_ADDRESS);
575+
576+
// Assert that multi-valued request parameters are preserved
577+
assertThat(authorizationCodeRequestAuthenticationCaptor.getValue().getAdditionalParameters())
578+
.extracting(ap -> ap.get("foo"))
579+
.asInstanceOf(type(String[].class))
580+
.isEqualTo(new String[] { "value1", "value2" });
573581
assertThat(response.getStatus()).isEqualTo(HttpStatus.FOUND.value());
574582
assertThat(response.getRedirectedUrl()).isEqualTo(
575583
"https://example.com?param=encoded%20parameter%20value&code=code&state=client%20state");

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilterTests.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,8 @@ public void doFilterWhenAuthorizationCodeTokenRequestThenAccessTokenResponse() t
273273
assertThat(authorizationCodeAuthentication.getRedirectUri()).isEqualTo(
274274
request.getParameter(OAuth2ParameterNames.REDIRECT_URI));
275275
assertThat(authorizationCodeAuthentication.getAdditionalParameters())
276-
.containsExactly(entry("custom-param-1", "custom-value-1"));
276+
.containsExactly(entry("custom-param-1", "custom-value-1"),
277+
entry("custom-param-2", new String[]{ "custom-value-2a", "custom-value-2b" }));
277278
assertThat(authorizationCodeAuthentication.getDetails())
278279
.asInstanceOf(type(WebAuthenticationDetails.class))
279280
.extracting(WebAuthenticationDetails::getRemoteAddress)
@@ -340,7 +341,8 @@ public void doFilterWhenClientCredentialsTokenRequestThenAccessTokenResponse() t
340341
assertThat(clientCredentialsAuthentication.getPrincipal()).isEqualTo(clientPrincipal);
341342
assertThat(clientCredentialsAuthentication.getScopes()).isEqualTo(registeredClient.getScopes());
342343
assertThat(clientCredentialsAuthentication.getAdditionalParameters())
343-
.containsExactly(entry("custom-param-1", "custom-value-1"));
344+
.containsExactly(entry("custom-param-1", "custom-value-1"),
345+
entry("custom-param-2", new String[]{ "custom-value-2a", "custom-value-2b" }));
344346
assertThat(clientCredentialsAuthentication.getDetails())
345347
.asInstanceOf(type(WebAuthenticationDetails.class))
346348
.extracting(WebAuthenticationDetails::getRemoteAddress)
@@ -430,7 +432,8 @@ public void doFilterWhenRefreshTokenRequestThenAccessTokenResponse() throws Exce
430432
assertThat(refreshTokenAuthenticationToken.getPrincipal()).isEqualTo(clientPrincipal);
431433
assertThat(refreshTokenAuthenticationToken.getScopes()).isEqualTo(registeredClient.getScopes());
432434
assertThat(refreshTokenAuthenticationToken.getAdditionalParameters())
433-
.containsExactly(entry("custom-param-1", "custom-value-1"));
435+
.containsExactly(entry("custom-param-1", "custom-value-1"),
436+
entry("custom-param-2", new String[]{ "custom-value-2a", "custom-value-2b" }));
434437
assertThat(refreshTokenAuthenticationToken.getDetails())
435438
.asInstanceOf(type(WebAuthenticationDetails.class))
436439
.extracting(WebAuthenticationDetails::getRemoteAddress)
@@ -613,6 +616,7 @@ private static MockHttpServletRequest createAuthorizationCodeTokenRequest(Regist
613616
// The client does not need to send the client ID param, but we are resilient in case they do
614617
request.addParameter(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId());
615618
request.addParameter("custom-param-1", "custom-value-1");
619+
request.addParameter("custom-param-2", "custom-value-2a", "custom-value-2b");
616620

617621
return request;
618622
}
@@ -627,6 +631,7 @@ private static MockHttpServletRequest createClientCredentialsTokenRequest(Regist
627631
request.addParameter(OAuth2ParameterNames.SCOPE,
628632
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
629633
request.addParameter("custom-param-1", "custom-value-1");
634+
request.addParameter("custom-param-2", "custom-value-2a", "custom-value-2b");
630635

631636
return request;
632637
}
@@ -642,6 +647,7 @@ private static MockHttpServletRequest createRefreshTokenTokenRequest(RegisteredC
642647
request.addParameter(OAuth2ParameterNames.SCOPE,
643648
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
644649
request.addParameter("custom-param-1", "custom-value-1");
650+
request.addParameter("custom-param-2", "custom-value-2a", "custom-value-2b");
645651

646652
return request;
647653
}

0 commit comments

Comments
 (0)