Pārlūkot izejas kodu

Move parametersCustomizer

The parametersCustomizer was introduced in 6.4.0-M4 with
DefaultOAuth2TokenRequestParametersConverter. However, it cannot be
applied to all parameters and so does not fully solve gh-11298.

This commit moves the customizer to the abstract class so it can be
applied to all parameters.

Closes gh-15939
Steve Riesenberg 10 mēneši atpakaļ
vecāks
revīzija
dab6950231
14 mainītis faili ar 153 papildinājumiem un 47 dzēšanām
  1. 16 0
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractRestClientOAuth2AccessTokenResponseClient.java
  2. 16 0
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java
  3. 0 17
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultOAuth2TokenRequestParametersConverter.java
  4. 10 6
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientAuthorizationCodeTokenResponseClientTests.java
  5. 10 6
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientClientCredentialsTokenResponseClientTests.java
  6. 10 6
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientJwtBearerTokenResponseClientTests.java
  7. 10 6
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientRefreshTokenTokenResponseClientTests.java
  8. 10 6
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientTokenExchangeTokenResponseClientTests.java
  9. 11 0
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java
  10. 12 0
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java
  11. 12 0
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClientTests.java
  12. 12 0
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClientTests.java
  13. 12 0
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java
  14. 12 0
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveTokenExchangeTokenResponseClientTests.java

+ 16 - 0
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractRestClientOAuth2AccessTokenResponseClient.java

@@ -16,6 +16,8 @@
 
 package org.springframework.security.oauth2.client.endpoint;
 
+import java.util.function.Consumer;
+
 import org.springframework.core.convert.converter.Converter;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.converter.FormHttpMessageConverter;
@@ -76,6 +78,9 @@ public abstract class AbstractRestClientOAuth2AccessTokenResponseClient<T extend
 
 	private Converter<T, MultiValueMap<String, String>> parametersConverter = new DefaultOAuth2TokenRequestParametersConverter<>();
 
+	private Consumer<MultiValueMap<String, String>> parametersCustomizer = (parameters) -> {
+	};
+
 	AbstractRestClientOAuth2AccessTokenResponseClient() {
 	}
 
@@ -127,6 +132,7 @@ public abstract class AbstractRestClientOAuth2AccessTokenResponseClient<T extend
 		if (parameters == null) {
 			parameters = new LinkedMultiValueMap<>();
 		}
+		this.parametersCustomizer.accept(parameters);
 
 		return this.restClient.post()
 			.uri(grantRequest.getClientRegistration().getProviderDetails().getTokenUri())
@@ -243,4 +249,14 @@ public abstract class AbstractRestClientOAuth2AccessTokenResponseClient<T extend
 		this.requestEntityConverter = this::populateRequest;
 	}
 
+	/**
+	 * Sets the {@link Consumer} used for customizing the OAuth 2.0 Access Token
+	 * parameters, which allows for parameters to be added, overwritten or removed.
+	 * @param parametersCustomizer the {@link Consumer} to customize the parameters
+	 */
+	public void setParametersCustomizer(Consumer<MultiValueMap<String, String>> parametersCustomizer) {
+		Assert.notNull(parametersCustomizer, "parametersCustomizer cannot be null");
+		this.parametersCustomizer = parametersCustomizer;
+	}
+
 }

+ 16 - 0
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java

@@ -16,6 +16,8 @@
 
 package org.springframework.security.oauth2.client.endpoint;
 
+import java.util.function.Consumer;
+
 import reactor.core.publisher.Mono;
 
 import org.springframework.core.convert.converter.Converter;
@@ -68,6 +70,9 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient<T
 
 	private Converter<T, MultiValueMap<String, String>> parametersConverter = new DefaultOAuth2TokenRequestParametersConverter<>();
 
+	private Consumer<MultiValueMap<String, String>> parametersCustomizer = (parameters) -> {
+	};
+
 	private BodyExtractor<Mono<OAuth2AccessTokenResponse>, ReactiveHttpInputMessage> bodyExtractor = OAuth2BodyExtractors
 		.oauth2AccessTokenResponse();
 
@@ -108,6 +113,7 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient<T
 		if (parameters == null) {
 			parameters = new LinkedMultiValueMap<>();
 		}
+		this.parametersCustomizer.accept(parameters);
 
 		return this.webClient.post()
 			.uri(grantRequest.getClientRegistration().getProviderDetails().getTokenUri())
@@ -228,6 +234,16 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient<T
 		this.requestEntityConverter = this::populateRequest;
 	}
 
+	/**
+	 * Sets the {@link Consumer} used for customizing the OAuth 2.0 Access Token
+	 * parameters, which allows for parameters to be added, overwritten or removed.
+	 * @param parametersCustomizer the {@link Consumer} to customize the parameters
+	 */
+	public void setParametersCustomizer(Consumer<MultiValueMap<String, String>> parametersCustomizer) {
+		Assert.notNull(parametersCustomizer, "parametersCustomizer cannot be null");
+		this.parametersCustomizer = parametersCustomizer;
+	}
+
 	/**
 	 * Sets the {@link BodyExtractor} that will be used to decode the
 	 * {@link OAuth2AccessTokenResponse}

+ 0 - 17
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultOAuth2TokenRequestParametersConverter.java

@@ -16,13 +16,10 @@
 
 package org.springframework.security.oauth2.client.endpoint;
 
-import java.util.function.Consumer;
-
 import org.springframework.core.convert.converter.Converter;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
-import org.springframework.util.Assert;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 
@@ -64,19 +61,6 @@ public final class DefaultOAuth2TokenRequestParametersConverter<T extends Abstra
 
 	private final Converter<T, MultiValueMap<String, String>> defaultParametersConverter = createDefaultParametersConverter();
 
-	private Consumer<MultiValueMap<String, String>> parametersCustomizer = (parameters) -> {
-	};
-
-	/**
-	 * Sets the {@link Consumer} used for customizing the OAuth 2.0 Access Token
-	 * parameters, which allows for parameters to be added, overwritten or removed.
-	 * @param parametersCustomizer the {@link Consumer} to customize the parameters
-	 */
-	public void setParametersCustomizer(Consumer<MultiValueMap<String, String>> parametersCustomizer) {
-		Assert.notNull(parametersCustomizer, "parametersCustomizer cannot be null");
-		this.parametersCustomizer = parametersCustomizer;
-	}
-
 	@Override
 	public MultiValueMap<String, String> convert(T grantRequest) {
 		ClientRegistration clientRegistration = grantRequest.getClientRegistration();
@@ -95,7 +79,6 @@ public final class DefaultOAuth2TokenRequestParametersConverter<T extends Abstra
 			parameters.addAll(defaultParameters);
 		}
 
-		this.parametersCustomizer.accept(parameters);
 		return parameters;
 	}
 

+ 10 - 6
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientAuthorizationCodeTokenResponseClientTests.java

@@ -154,6 +154,15 @@ public class RestClientAuthorizationCodeTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void setParametersCustomizerWhenNullThenThrowIllegalArgumentException() {
+		// @formatter:off
+		assertThatIllegalArgumentException()
+			.isThrownBy(() -> this.tokenResponseClient.setParametersCustomizer(null))
+			.withMessage("parametersCustomizer cannot be null");
+		// @formatter:on
+	}
+
 	@Test
 	public void getTokenResponseWhenGrantRequestIsNullThenThrowIllegalArgumentException() {
 		// @formatter:off
@@ -439,12 +448,7 @@ public class RestClientAuthorizationCodeTokenResponseClientTests {
 		OAuth2AuthorizationCodeGrantRequest grantRequest = new OAuth2AuthorizationCodeGrantRequest(clientRegistration,
 				this.authorizationExchange);
 		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
-		// @formatter:off
-		DefaultOAuth2TokenRequestParametersConverter<OAuth2AuthorizationCodeGrantRequest> parametersConverter =
-			new DefaultOAuth2TokenRequestParametersConverter<>();
-		// @formatter:on
-		parametersConverter.setParametersCustomizer(parametersCustomizer);
-		this.tokenResponseClient.setParametersConverter(parametersConverter);
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
 		this.tokenResponseClient.getTokenResponse(grantRequest);
 		verify(parametersCustomizer).accept(any());
 	}

+ 10 - 6
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientClientCredentialsTokenResponseClientTests.java

@@ -138,6 +138,15 @@ public class RestClientClientCredentialsTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void setParametersCustomizerWhenNullThenThrowIllegalArgumentException() {
+		// @formatter:off
+		assertThatIllegalArgumentException()
+			.isThrownBy(() -> this.tokenResponseClient.setParametersCustomizer(null))
+			.withMessage("parametersCustomizer cannot be null");
+		// @formatter:on
+	}
+
 	@Test
 	public void getTokenResponseWhenGrantRequestIsNullThenThrowIllegalArgumentException() {
 		// @formatter:off
@@ -438,12 +447,7 @@ public class RestClientClientCredentialsTokenResponseClientTests {
 		ClientRegistration clientRegistration = this.clientRegistration.build();
 		OAuth2ClientCredentialsGrantRequest grantRequest = new OAuth2ClientCredentialsGrantRequest(clientRegistration);
 		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
-		// @formatter:off
-		DefaultOAuth2TokenRequestParametersConverter<OAuth2ClientCredentialsGrantRequest> parametersConverter =
-			new DefaultOAuth2TokenRequestParametersConverter<>();
-		// @formatter:on
-		parametersConverter.setParametersCustomizer(parametersCustomizer);
-		this.tokenResponseClient.setParametersConverter(parametersConverter);
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
 		this.tokenResponseClient.getTokenResponse(grantRequest);
 		verify(parametersCustomizer).accept(any());
 	}

+ 10 - 6
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientJwtBearerTokenResponseClientTests.java

@@ -140,6 +140,15 @@ public class RestClientJwtBearerTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void setParametersCustomizerWhenNullThenThrowIllegalArgumentException() {
+		// @formatter:off
+		assertThatIllegalArgumentException()
+			.isThrownBy(() -> this.tokenResponseClient.setParametersCustomizer(null))
+			.withMessage("parametersCustomizer cannot be null");
+		// @formatter:on
+	}
+
 	@Test
 	public void getTokenResponseWhenGrantRequestIsNullThenThrowIllegalArgumentException() {
 		// @formatter:off
@@ -414,12 +423,7 @@ public class RestClientJwtBearerTokenResponseClientTests {
 		ClientRegistration clientRegistration = this.clientRegistration.build();
 		JwtBearerGrantRequest grantRequest = new JwtBearerGrantRequest(clientRegistration, this.jwtAssertion);
 		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
-		// @formatter:off
-		DefaultOAuth2TokenRequestParametersConverter<JwtBearerGrantRequest> parametersConverter =
-			new DefaultOAuth2TokenRequestParametersConverter<>();
-		// @formatter:on
-		parametersConverter.setParametersCustomizer(parametersCustomizer);
-		this.tokenResponseClient.setParametersConverter(parametersConverter);
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
 		this.tokenResponseClient.getTokenResponse(grantRequest);
 		verify(parametersCustomizer).accept(any());
 	}

+ 10 - 6
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientRefreshTokenTokenResponseClientTests.java

@@ -147,6 +147,15 @@ public class RestClientRefreshTokenTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void setParametersCustomizerWhenNullThenThrowIllegalArgumentException() {
+		// @formatter:off
+		assertThatIllegalArgumentException()
+			.isThrownBy(() -> this.tokenResponseClient.setParametersCustomizer(null))
+			.withMessage("parametersCustomizer cannot be null");
+		// @formatter:on
+	}
+
 	@Test
 	public void getTokenResponseWhenGrantRequestIsNullThenThrowIllegalArgumentException() {
 		// @formatter:off
@@ -461,12 +470,7 @@ public class RestClientRefreshTokenTokenResponseClientTests {
 		OAuth2RefreshTokenGrantRequest grantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration,
 				this.accessToken, this.refreshToken);
 		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
-		// @formatter:off
-		DefaultOAuth2TokenRequestParametersConverter<OAuth2RefreshTokenGrantRequest> parametersConverter =
-			new DefaultOAuth2TokenRequestParametersConverter<>();
-		// @formatter:on
-		parametersConverter.setParametersCustomizer(parametersCustomizer);
-		this.tokenResponseClient.setParametersConverter(parametersConverter);
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
 		this.tokenResponseClient.getTokenResponse(grantRequest);
 		verify(parametersCustomizer).accept(any());
 	}

+ 10 - 6
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/RestClientTokenExchangeTokenResponseClientTests.java

@@ -148,6 +148,15 @@ public class RestClientTokenExchangeTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void setParametersCustomizerWhenNullThenThrowIllegalArgumentException() {
+		// @formatter:off
+		assertThatIllegalArgumentException()
+			.isThrownBy(() -> this.tokenResponseClient.setParametersCustomizer(null))
+			.withMessage("parametersCustomizer cannot be null");
+		// @formatter:on
+	}
+
 	@Test
 	public void getTokenResponseWhenGrantRequestIsNullThenThrowIllegalArgumentException() {
 		// @formatter:off
@@ -545,12 +554,7 @@ public class RestClientTokenExchangeTokenResponseClientTests {
 		TokenExchangeGrantRequest grantRequest = new TokenExchangeGrantRequest(clientRegistration, this.subjectToken,
 				this.actorToken);
 		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
-		// @formatter:off
-		DefaultOAuth2TokenRequestParametersConverter<TokenExchangeGrantRequest> parametersConverter =
-			new DefaultOAuth2TokenRequestParametersConverter<>();
-		// @formatter:on
-		parametersConverter.setParametersCustomizer(parametersCustomizer);
-		this.tokenResponseClient.setParametersConverter(parametersConverter);
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
 		this.tokenResponseClient.getTokenResponse(grantRequest);
 		verify(parametersCustomizer).accept(any());
 	}

+ 11 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java

@@ -22,6 +22,7 @@ import java.time.Instant;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 import javax.crypto.spec.SecretKeySpec;
@@ -406,6 +407,16 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void getTokenResponseWhenParametersCustomizerSetThenCalled() throws Exception {
+		this.server.enqueue(MockResponses.json("access-token-response.json"));
+		OAuth2AuthorizationCodeGrantRequest request = authorizationCodeGrantRequest();
+		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
+		this.tokenResponseClient.getTokenResponse(request).block();
+		verify(parametersCustomizer).accept(any());
+	}
+
 	// gh-10260
 	@Test
 	public void getTokenResponseWhenSuccessCustomResponseThenReturnAccessTokenResponse() {

+ 12 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java

@@ -20,6 +20,7 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 import java.util.Collections;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 import javax.crypto.spec.SecretKeySpec;
@@ -365,6 +366,17 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void getTokenResponseWhenParametersCustomizerSetThenCalled() throws Exception {
+		this.server.enqueue(MockResponses.json("access-token-response.json"));
+		OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(
+				this.clientRegistration.build());
+		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
+		this.client.setParametersCustomizer(parametersCustomizer);
+		this.client.getTokenResponse(request).block();
+		verify(parametersCustomizer).accept(any());
+	}
+
 	// gh-10260
 	@Test
 	public void getTokenResponseWhenSuccessCustomResponseThenReturnAccessTokenResponse() {

+ 12 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClientTests.java

@@ -19,6 +19,7 @@ package org.springframework.security.oauth2.client.endpoint;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
+import java.util.function.Consumer;
 
 import okhttp3.mockwebserver.MockResponse;
 import okhttp3.mockwebserver.MockWebServer;
@@ -289,6 +290,17 @@ public class WebClientReactiveJwtBearerTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void getTokenResponseWhenParametersCustomizerSetThenCalled() throws Exception {
+		this.server.enqueue(MockResponses.json("access-token-response.json"));
+		ClientRegistration clientRegistration = this.clientRegistration.build();
+		JwtBearerGrantRequest request = new JwtBearerGrantRequest(clientRegistration, this.jwtAssertion);
+		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
+		this.client.setParametersCustomizer(parametersCustomizer);
+		this.client.getTokenResponse(request).block();
+		verify(parametersCustomizer).accept(any());
+	}
+
 	@Test
 	public void getTokenResponseWhenBodyExtractorSetThenCalled() {
 		BodyExtractor<Mono<OAuth2AccessTokenResponse>, ReactiveHttpInputMessage> bodyExtractor = mock();

+ 12 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClientTests.java

@@ -20,6 +20,7 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 import java.util.Collections;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 import javax.crypto.spec.SecretKeySpec;
@@ -408,6 +409,17 @@ public class WebClientReactivePasswordTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void getTokenResponseWhenParametersCustomizerSetThenCalled() throws Exception {
+		this.server.enqueue(MockResponses.json("access-token-response.json"));
+		OAuth2PasswordGrantRequest request = new OAuth2PasswordGrantRequest(this.clientRegistrationBuilder.build(),
+				this.username, this.password);
+		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
+		this.tokenResponseClient.getTokenResponse(request).block();
+		verify(parametersCustomizer).accept(any());
+	}
+
 	// gh-10260
 	@Test
 	public void getTokenResponseWhenSuccessCustomResponseThenReturnAccessTokenResponse() {

+ 12 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java

@@ -20,6 +20,7 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 import java.util.Collections;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 import javax.crypto.spec.SecretKeySpec;
@@ -378,6 +379,17 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void getTokenResponseWhenParametersCustomizerSetThenCalled() throws Exception {
+		this.server.enqueue(MockResponses.json("access-token-response.json"));
+		OAuth2RefreshTokenGrantRequest request = new OAuth2RefreshTokenGrantRequest(
+				this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken);
+		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
+		this.tokenResponseClient.getTokenResponse(request).block();
+		verify(parametersCustomizer).accept(any());
+	}
+
 	// gh-10260
 	@Test
 	public void getTokenResponseWhenSuccessCustomResponseThenReturnAccessTokenResponse() {

+ 12 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveTokenExchangeTokenResponseClientTests.java

@@ -21,6 +21,7 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 import java.util.Collections;
+import java.util.function.Consumer;
 
 import okhttp3.mockwebserver.MockResponse;
 import okhttp3.mockwebserver.MockWebServer;
@@ -529,6 +530,17 @@ public class WebClientReactiveTokenExchangeTokenResponseClientTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void getTokenResponseWhenParametersCustomizerSetThenCalled() throws Exception {
+		this.server.enqueue(MockResponses.json("access-token-response.json"));
+		TokenExchangeGrantRequest request = new TokenExchangeGrantRequest(this.clientRegistration.build(),
+				this.subjectToken, this.actorToken);
+		Consumer<MultiValueMap<String, String>> parametersCustomizer = mock();
+		this.tokenResponseClient.setParametersCustomizer(parametersCustomizer);
+		this.tokenResponseClient.getTokenResponse(request).block();
+		verify(parametersCustomizer).accept(any());
+	}
+
 	@Test
 	public void getTokenResponseWhenBodyExtractorSetThenCalled() {
 		this.server.enqueue(MockResponses.json("access-token-response.json"));