From d7ca009f0f1bbd9cf70423c1c48cdea11c663c2d Mon Sep 17 00:00:00 2001 From: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:09:05 -0500 Subject: [PATCH] Refactor AbstractWebClientReactiveOAuth2AccessTokenResponseClient Issue gh-14811 --- ...activeOAuth2AccessTokenResponseClient.java | 163 +++--------------- ...eAuthorizationCodeTokenResponseClient.java | 32 +--- ...eClientCredentialsTokenResponseClient.java | 13 -- ...tReactiveJwtBearerTokenResponseClient.java | 23 +-- ...ntReactivePasswordTokenResponseClient.java | 25 +-- ...activeRefreshTokenTokenResponseClient.java | 38 ++-- ...ctiveTokenExchangeTokenResponseClient.java | 32 +--- 7 files changed, 66 insertions(+), 260 deletions(-) diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java index 14d403d9880..1f679243ec4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java @@ -16,9 +16,6 @@ package org.springframework.security.oauth2.client.endpoint; -import java.util.Collections; -import java.util.Set; - import reactor.core.publisher.Mono; import org.springframework.core.convert.converter.Converter; @@ -36,7 +33,6 @@ import org.springframework.util.StringUtils; import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec; @@ -54,6 +50,7 @@ * * @param type of grant request * @author Phil Clay + * @author Steve Riesenberg * @since 5.3 * @see RFC-6749 Token * Endpoint @@ -72,7 +69,7 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient headersConverter = new DefaultOAuth2TokenRequestHeadersConverter<>(); - private Converter> parametersConverter = this::populateTokenRequestParameters; + private Converter> parametersConverter = this::createParameters; private BodyExtractor, ReactiveHttpInputMessage> bodyExtractor = OAuth2BodyExtractors .oauth2AccessTokenResponse(); @@ -86,18 +83,11 @@ public Mono getTokenResponse(T grantRequest) { // @formatter:off return Mono.defer(() -> this.requestEntityConverter.convert(grantRequest) .exchange() - .flatMap((response) -> readTokenResponse(grantRequest, response)) + .flatMap((response) -> response.body(this.bodyExtractor)) ); // @formatter:on } - /** - * Returns the {@link ClientRegistration} for the given {@code grantRequest}. - * @param grantRequest the grant request - * @return the {@link ClientRegistration} for the given {@code grantRequest}. - */ - abstract ClientRegistration clientRegistration(T grantRequest); - private RequestHeadersSpec validatingPopulateRequest(T grantRequest) { validateClientAuthenticationMethod(grantRequest); return populateRequest(grantRequest); @@ -117,128 +107,41 @@ private void validateClientAuthenticationMethod(T grantRequest) { } private RequestHeadersSpec populateRequest(T grantRequest) { + MultiValueMap parameters = this.parametersConverter.convert(grantRequest); return this.webClient.post() - .uri(clientRegistration(grantRequest).getProviderDetails().getTokenUri()) + .uri(grantRequest.getClientRegistration().getProviderDetails().getTokenUri()) .headers((headers) -> { - HttpHeaders headersToAdd = getHeadersConverter().convert(grantRequest); + HttpHeaders headersToAdd = this.headersConverter.convert(grantRequest); if (headersToAdd != null) { headers.addAll(headersToAdd); } }) - .body(createTokenRequestBody(grantRequest)); + .body(BodyInserters.fromFormData(parameters)); } /** - * Populates default parameters for the token request. - * @param grantRequest the grant request - * @return the parameters populated for the token request. + * Returns a {@link MultiValueMap} of the parameters used in the OAuth 2.0 Access + * Token Request body. + * @param grantRequest the authorization grant request + * @return a {@link MultiValueMap} of the parameters used in the OAuth 2.0 Access + * Token Request body */ - private MultiValueMap populateTokenRequestParameters(T grantRequest) { + MultiValueMap createParameters(T grantRequest) { + ClientRegistration clientRegistration = grantRequest.getClientRegistration(); MultiValueMap parameters = new LinkedMultiValueMap<>(); - parameters.add(OAuth2ParameterNames.GRANT_TYPE, grantRequest.getGrantType().getValue()); - return parameters; - } - - /** - * Combine the results of {@code parametersConverter} and - * {@link #populateTokenRequestBody}. - * - *

- * This method pre-populates the body with some standard properties, and then - * delegates to - * {@link #populateTokenRequestBody(AbstractOAuth2AuthorizationGrantRequest, BodyInserters.FormInserter)} - * for subclasses to further populate the body before returning. - *

- * @param grantRequest the grant request - * @return the body for the token request. - */ - private BodyInserters.FormInserter createTokenRequestBody(T grantRequest) { - MultiValueMap parameters = getParametersConverter().convert(grantRequest); - return populateTokenRequestBody(grantRequest, BodyInserters.fromFormData(parameters)); - } - - /** - * Populates the body of the token request. - * - *

- * By default, populates properties that are common to all grant types. Subclasses can - * extend this method to populate grant type specific properties. - *

- * @param grantRequest the grant request - * @param body the body to populate - * @return the populated body - */ - BodyInserters.FormInserter populateTokenRequestBody(T grantRequest, - BodyInserters.FormInserter body) { - ClientRegistration clientRegistration = clientRegistration(grantRequest); + parameters.set(OAuth2ParameterNames.GRANT_TYPE, grantRequest.getGrantType().getValue()); if (!ClientAuthenticationMethod.CLIENT_SECRET_BASIC .equals(clientRegistration.getClientAuthenticationMethod())) { - body.with(OAuth2ParameterNames.CLIENT_ID, clientRegistration.getClientId()); + parameters.set(OAuth2ParameterNames.CLIENT_ID, clientRegistration.getClientId()); } if (ClientAuthenticationMethod.CLIENT_SECRET_POST.equals(clientRegistration.getClientAuthenticationMethod())) { - body.with(OAuth2ParameterNames.CLIENT_SECRET, clientRegistration.getClientSecret()); + parameters.set(OAuth2ParameterNames.CLIENT_SECRET, clientRegistration.getClientSecret()); } - Set scopes = scopes(grantRequest); - if (!CollectionUtils.isEmpty(scopes)) { - body.with(OAuth2ParameterNames.SCOPE, StringUtils.collectionToDelimitedString(scopes, " ")); + if (!CollectionUtils.isEmpty(clientRegistration.getScopes())) { + parameters.set(OAuth2ParameterNames.SCOPE, + StringUtils.collectionToDelimitedString(clientRegistration.getScopes(), " ")); } - return body; - } - - /** - * Returns the scopes to include as a property in the token request. - * @param grantRequest the grant request - * @return the scopes to include as a property in the token request. - */ - abstract Set scopes(T grantRequest); - - /** - * Returns the scopes to include in the response if the authorization server returned - * no scopes in the response. - * - *

- * As per RFC-6749 Section - * 5.1 Successful Access Token Response, if AccessTokenResponse.scope is empty, - * then default to the scope originally requested by the client in the Token Request. - *

- * @param grantRequest the grant request - * @return the scopes to include in the response if the authorization server returned - * no scopes. - */ - Set defaultScopes(T grantRequest) { - return Collections.emptySet(); - } - - /** - * Reads the token response from the response body. - * @param grantRequest the request for which the response was received. - * @param response the client response from which to read - * @return the token response from the response body. - */ - private Mono readTokenResponse(T grantRequest, ClientResponse response) { - return response.body(this.bodyExtractor) - .map((tokenResponse) -> populateTokenResponse(grantRequest, tokenResponse)); - } - - /** - * Populates the given {@link OAuth2AccessTokenResponse} with additional details from - * the grant request. - * @param grantRequest the request for which the response was received. - * @param tokenResponse the original token response - * @return a token response optionally populated with additional details from the - * request. - */ - OAuth2AccessTokenResponse populateTokenResponse(T grantRequest, OAuth2AccessTokenResponse tokenResponse) { - if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) { - Set defaultScopes = defaultScopes(grantRequest); - // @formatter:off - tokenResponse = OAuth2AccessTokenResponse - .withResponse(tokenResponse) - .scopes(defaultScopes) - .build(); - // @formatter:on - } - return tokenResponse; + return parameters; } /** @@ -247,22 +150,11 @@ OAuth2AccessTokenResponse populateTokenResponse(T grantRequest, OAuth2AccessToke * @param webClient the {@link WebClient} used when requesting the Access Token * Response */ - public void setWebClient(WebClient webClient) { + public final void setWebClient(WebClient webClient) { Assert.notNull(webClient, "webClient cannot be null"); this.webClient = webClient; } - /** - * Returns the {@link Converter} used for converting the - * {@link AbstractOAuth2AuthorizationGrantRequest} instance to a {@link HttpHeaders} - * used in the OAuth 2.0 Access Token Request headers. - * @return the {@link Converter} used for converting the - * {@link AbstractOAuth2AuthorizationGrantRequest} to {@link HttpHeaders} - */ - final Converter getHeadersConverter() { - return this.headersConverter; - } - /** * Sets the {@link Converter} used for converting the * {@link AbstractOAuth2AuthorizationGrantRequest} instance to a {@link HttpHeaders} @@ -305,17 +197,6 @@ public final void addHeadersConverter(Converter headersConverter this.requestEntityConverter = this::populateRequest; } - /** - * Returns the {@link Converter} used for converting the - * {@link AbstractOAuth2AuthorizationGrantRequest} instance to a {@link MultiValueMap} - * used in the OAuth 2.0 Access Token Request body. - * @return the {@link Converter} used for converting the - * {@link AbstractOAuth2AuthorizationGrantRequest} to {@link MultiValueMap} - */ - final Converter> getParametersConverter() { - return this.parametersConverter; - } - /** * Sets the {@link Converter} used for converting the * {@link AbstractOAuth2AuthorizationGrantRequest} instance to a {@link MultiValueMap} diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java index ba5ad0cf69a..002fd4020ac 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java @@ -16,16 +16,11 @@ package org.springframework.security.oauth2.client.endpoint; -import java.util.Collections; -import java.util.Set; - -import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.security.oauth2.core.endpoint.PkceParameterNames; -import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.util.MultiValueMap; /** * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} that @@ -56,32 +51,21 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClient extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override - ClientRegistration clientRegistration(OAuth2AuthorizationCodeGrantRequest grantRequest) { - return grantRequest.getClientRegistration(); - } - - @Override - Set scopes(OAuth2AuthorizationCodeGrantRequest grantRequest) { - return Collections.emptySet(); - } - - @Override - BodyInserters.FormInserter populateTokenRequestBody(OAuth2AuthorizationCodeGrantRequest grantRequest, - BodyInserters.FormInserter body) { - super.populateTokenRequestBody(grantRequest, body); + MultiValueMap createParameters(OAuth2AuthorizationCodeGrantRequest grantRequest) { OAuth2AuthorizationExchange authorizationExchange = grantRequest.getAuthorizationExchange(); - OAuth2AuthorizationResponse authorizationResponse = authorizationExchange.getAuthorizationResponse(); - body.with(OAuth2ParameterNames.CODE, authorizationResponse.getCode()); + MultiValueMap parameters = super.createParameters(grantRequest); + parameters.remove(OAuth2ParameterNames.SCOPE); + parameters.set(OAuth2ParameterNames.CODE, authorizationExchange.getAuthorizationResponse().getCode()); String redirectUri = authorizationExchange.getAuthorizationRequest().getRedirectUri(); if (redirectUri != null) { - body.with(OAuth2ParameterNames.REDIRECT_URI, redirectUri); + parameters.set(OAuth2ParameterNames.REDIRECT_URI, redirectUri); } String codeVerifier = authorizationExchange.getAuthorizationRequest() .getAttribute(PkceParameterNames.CODE_VERIFIER); if (codeVerifier != null) { - body.with(PkceParameterNames.CODE_VERIFIER, codeVerifier); + parameters.set(PkceParameterNames.CODE_VERIFIER, codeVerifier); } - return body; + return parameters; } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java index f7df261b6b2..bce715fe763 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java @@ -16,9 +16,6 @@ package org.springframework.security.oauth2.client.endpoint; -import java.util.Set; - -import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; /** @@ -44,14 +41,4 @@ public class WebClientReactiveClientCredentialsTokenResponseClient extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { - @Override - ClientRegistration clientRegistration(OAuth2ClientCredentialsGrantRequest grantRequest) { - return grantRequest.getClientRegistration(); - } - - @Override - Set scopes(OAuth2ClientCredentialsGrantRequest grantRequest) { - return grantRequest.getClientRegistration().getScopes(); - } - } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClient.java index 157f00be510..ef8e87202b1 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClient.java @@ -16,13 +16,10 @@ package org.springframework.security.oauth2.client.endpoint; -import java.util.Set; - -import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; -import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.client.WebClient; /** @@ -45,20 +42,10 @@ public final class WebClientReactiveJwtBearerTokenResponseClient extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override - ClientRegistration clientRegistration(JwtBearerGrantRequest grantRequest) { - return grantRequest.getClientRegistration(); - } - - @Override - Set scopes(JwtBearerGrantRequest grantRequest) { - return grantRequest.getClientRegistration().getScopes(); - } - - @Override - BodyInserters.FormInserter populateTokenRequestBody(JwtBearerGrantRequest grantRequest, - BodyInserters.FormInserter body) { - return super.populateTokenRequestBody(grantRequest, body).with(OAuth2ParameterNames.ASSERTION, - grantRequest.getJwt().getTokenValue()); + MultiValueMap createParameters(JwtBearerGrantRequest grantRequest) { + MultiValueMap parameters = super.createParameters(grantRequest); + parameters.set(OAuth2ParameterNames.ASSERTION, grantRequest.getJwt().getTokenValue()); + return parameters; } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java index e175b3b37c8..05a4e2310b3 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java @@ -16,13 +16,10 @@ package org.springframework.security.oauth2.client.endpoint; -import java.util.Set; - -import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; -import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.client.WebClient; /** @@ -52,21 +49,11 @@ public final class WebClientReactivePasswordTokenResponseClient extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override - ClientRegistration clientRegistration(OAuth2PasswordGrantRequest grantRequest) { - return grantRequest.getClientRegistration(); - } - - @Override - Set scopes(OAuth2PasswordGrantRequest grantRequest) { - return grantRequest.getClientRegistration().getScopes(); - } - - @Override - BodyInserters.FormInserter populateTokenRequestBody(OAuth2PasswordGrantRequest grantRequest, - BodyInserters.FormInserter body) { - return super.populateTokenRequestBody(grantRequest, body) - .with(OAuth2ParameterNames.USERNAME, grantRequest.getUsername()) - .with(OAuth2ParameterNames.PASSWORD, grantRequest.getPassword()); + MultiValueMap createParameters(OAuth2PasswordGrantRequest grantRequest) { + MultiValueMap parameters = super.createParameters(grantRequest); + parameters.set(OAuth2ParameterNames.USERNAME, grantRequest.getUsername()); + parameters.set(OAuth2ParameterNames.PASSWORD, grantRequest.getPassword()); + return parameters; } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java index 0c814a13e5c..8a482121aaa 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java @@ -16,14 +16,14 @@ package org.springframework.security.oauth2.client.endpoint; -import java.util.Set; +import reactor.core.publisher.Mono; -import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.util.CollectionUtils; -import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; import org.springframework.web.reactive.function.client.WebClient; /** @@ -44,29 +44,23 @@ public final class WebClientReactiveRefreshTokenTokenResponseClient extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override - ClientRegistration clientRegistration(OAuth2RefreshTokenGrantRequest grantRequest) { - return grantRequest.getClientRegistration(); + public Mono getTokenResponse(OAuth2RefreshTokenGrantRequest grantRequest) { + return super.getTokenResponse(grantRequest) + .map((accessTokenResponse) -> populateTokenResponse(grantRequest, accessTokenResponse)); } @Override - Set scopes(OAuth2RefreshTokenGrantRequest grantRequest) { - return grantRequest.getScopes(); - } - - @Override - Set defaultScopes(OAuth2RefreshTokenGrantRequest grantRequest) { - return grantRequest.getAccessToken().getScopes(); - } - - @Override - BodyInserters.FormInserter populateTokenRequestBody(OAuth2RefreshTokenGrantRequest grantRequest, - BodyInserters.FormInserter body) { - return super.populateTokenRequestBody(grantRequest, body).with(OAuth2ParameterNames.REFRESH_TOKEN, - grantRequest.getRefreshToken().getTokenValue()); + MultiValueMap createParameters(OAuth2RefreshTokenGrantRequest grantRequest) { + MultiValueMap parameters = super.createParameters(grantRequest); + if (!CollectionUtils.isEmpty(grantRequest.getScopes())) { + parameters.add(OAuth2ParameterNames.SCOPE, + StringUtils.collectionToDelimitedString(grantRequest.getScopes(), " ")); + } + parameters.set(OAuth2ParameterNames.REFRESH_TOKEN, grantRequest.getRefreshToken().getTokenValue()); + return parameters; } - @Override - OAuth2AccessTokenResponse populateTokenResponse(OAuth2RefreshTokenGrantRequest grantRequest, + private OAuth2AccessTokenResponse populateTokenResponse(OAuth2RefreshTokenGrantRequest grantRequest, OAuth2AccessTokenResponse accessTokenResponse) { if (!CollectionUtils.isEmpty(accessTokenResponse.getAccessToken().getScopes()) && accessTokenResponse.getRefreshToken() != null) { @@ -75,7 +69,7 @@ OAuth2AccessTokenResponse populateTokenResponse(OAuth2RefreshTokenGrantRequest g OAuth2AccessTokenResponse.Builder tokenResponseBuilder = OAuth2AccessTokenResponse .withResponse(accessTokenResponse); if (CollectionUtils.isEmpty(accessTokenResponse.getAccessToken().getScopes())) { - tokenResponseBuilder.scopes(defaultScopes(grantRequest)); + tokenResponseBuilder.scopes(grantRequest.getAccessToken().getScopes()); } if (accessTokenResponse.getRefreshToken() == null) { // Reuse existing refresh token diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveTokenExchangeTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveTokenExchangeTokenResponseClient.java index abc9ad751b8..b87a2d7e08f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveTokenExchangeTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveTokenExchangeTokenResponseClient.java @@ -16,15 +16,12 @@ package org.springframework.security.oauth2.client.endpoint; -import java.util.Set; - -import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.OAuth2Token; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.client.WebClient; /** @@ -51,29 +48,18 @@ public final class WebClientReactiveTokenExchangeTokenResponseClient private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt"; @Override - ClientRegistration clientRegistration(TokenExchangeGrantRequest grantRequest) { - return grantRequest.getClientRegistration(); - } - - @Override - Set scopes(TokenExchangeGrantRequest grantRequest) { - return grantRequest.getClientRegistration().getScopes(); - } - - @Override - BodyInserters.FormInserter populateTokenRequestBody(TokenExchangeGrantRequest grantRequest, - BodyInserters.FormInserter body) { - super.populateTokenRequestBody(grantRequest, body); - body.with(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE, ACCESS_TOKEN_TYPE_VALUE); + MultiValueMap createParameters(TokenExchangeGrantRequest grantRequest) { + MultiValueMap parameters = super.createParameters(grantRequest); + parameters.set(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE, ACCESS_TOKEN_TYPE_VALUE); OAuth2Token subjectToken = grantRequest.getSubjectToken(); - body.with(OAuth2ParameterNames.SUBJECT_TOKEN, subjectToken.getTokenValue()); - body.with(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE, tokenType(subjectToken)); + parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN, subjectToken.getTokenValue()); + parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE, tokenType(subjectToken)); OAuth2Token actorToken = grantRequest.getActorToken(); if (actorToken != null) { - body.with(OAuth2ParameterNames.ACTOR_TOKEN, actorToken.getTokenValue()); - body.with(OAuth2ParameterNames.ACTOR_TOKEN_TYPE, tokenType(actorToken)); + parameters.set(OAuth2ParameterNames.ACTOR_TOKEN, actorToken.getTokenValue()); + parameters.set(OAuth2ParameterNames.ACTOR_TOKEN_TYPE, tokenType(actorToken)); } - return body; + return parameters; } private static String tokenType(OAuth2Token token) {