From 24dbc5de535bd8a2617e2c8078e797239f6077dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9C=B3=E4=BD=B3?= Date: Wed, 7 Aug 2024 13:35:34 +0800 Subject: [PATCH] Fix array values of additionalParameters Closes gh-15468 --- .../endpoint/OAuth2AuthorizationRequest.java | 26 +++++++++++++++++-- .../OAuth2AuthorizationRequestTests.java | 23 ++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequest.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequest.java index 8522af771c..c4a1b9516e 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequest.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequest.java @@ -23,11 +23,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; - +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.util.Assert; @@ -440,7 +442,13 @@ public final class OAuth2AuthorizationRequest implements Serializable { Map parameters = getParameters(); // Not encoded this.parametersConsumer.accept(parameters); MultiValueMap queryParams = new LinkedMultiValueMap<>(); - parameters.forEach((k, v) -> queryParams.set(encodeQueryParam(k), encodeQueryParam(String.valueOf(v)))); // Encoded + parameters.forEach((key1, value) -> { + String key = encodeQueryParam(key1); + List values = queryValues(value) + .map(o -> encodeQueryParam(String.valueOf(o))) + .toList(); + queryParams.put(key, values); + }); UriBuilder uriBuilder = this.uriBuilderFactory.uriString(this.authorizationUri).queryParams(queryParams); return this.authorizationRequestUriFunction.apply(uriBuilder).toString(); } @@ -467,6 +475,20 @@ public final class OAuth2AuthorizationRequest implements Serializable { return UriUtils.encodeQueryParam(value, StandardCharsets.UTF_8); } + // Query value as a stream + // If the value is an Iterable or an array it will be converted to a stream + private static Stream queryValues(Object value) { + if (value instanceof Iterable) { + return StreamSupport.stream(((Iterable) value).spliterator(), false); + + } else if (value.getClass().isArray()) { + return Arrays.stream((Object[]) value); + + } else { + return Stream.of(value); + } + } + } } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java index 1a912d58a8..f70d418ef0 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java @@ -16,20 +16,18 @@ package org.springframework.security.oauth2.core.endpoint; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + import java.net.URI; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; - import org.junit.jupiter.api.Test; - import org.springframework.security.oauth2.core.AuthorizationGrantType; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - /** * Tests for {@link OAuth2AuthorizationRequest}. * @@ -319,4 +317,19 @@ public class OAuth2AuthorizationRequestTests { + "item%20amount=19.95%E2%82%AC&%C3%A2ge=4%C2%BD&item%20name=H%C3%85M%C3%96"); } + @Test + public void additionalParametersArrayValueOrIterableEncoded() { + Map additionalParameters = new HashMap<>(); + additionalParameters.put("item", new String[] { "1", "2" }); + additionalParameters.put("item2", Arrays.asList("H" + '\u00c5' + "M" + '\u00d6', "H" + '\u00c5' + "M" + '\u00d6')); + OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() + .additionalParameters(additionalParameters) + .build(); + assertThat(authorizationRequest.getAuthorizationRequestUri()).isNotNull(); + assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo( + "https://example.com/login/oauth/authorize?" + "response_type=code&client_id=client-id&state=state&" + + "redirect_uri=https://example.com/authorize/oauth2/code/registration-id&" + + "item=1&item=2&item2=H%C3%85M%C3%96&item2=H%C3%85M%C3%96"); + } + }