spring-cloud-gateway
spring-cloud-gateway copied to clipboard
Unable to customize ReactiveOAuth2AccessTokenResponseClient for refresh token
Hi,
I'm using spring boot 3.3.1/spring-cloud-starter-gateway (reactive)/ spring-boot-starter-oauth2-client. My Oauth2 / OIDC Provider is behind an HTTP Proxy. I need to customize the WebClient, in order to configure the HttpProxy.
Following the documentation, i have created 2 beans :
@Bean
public ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() {
WebClientReactiveAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new WebClientReactiveAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.setWebClient(webClient());
return accessTokenResponseClient;
}
@Bean
public ReactiveOAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() {
WebClientReactiveRefreshTokenTokenResponseClient accessTokenResponseClient =
new WebClientReactiveRefreshTokenTokenResponseClient();
accessTokenResponseClient.setWebClient(webClient());
return accessTokenResponseClient;
}
private static WebClient webClient() {
final HttpClient httpClient = HttpClient.create().proxyWithSystemProperties();
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
When the application receive the authorization code, spring security call the token endpoint and receive the access token. The custom bean WebClientReactiveAuthorizationCodeTokenResponseClient is used, and the http query go through the proxy
But when spring security call the endpoint to refresh the token, it doesn't work. The custom WebClientReactiveAuthorizationCodeTokenResponseClient is not used.
I put some breakpoint, the second bean is instantiated but in method RefreshTokenReactiveOAuth2AuthorizedClientProvider.authorize, the accessTokenResponseClient is not my custom bean, but the default one :
@Override
public Mono<OAuth2AuthorizedClient> authorize(OAuth2AuthorizationContext context) {
return Mono.just(refreshTokenGrantRequest)
.flatMap(this.accessTokenResponseClient::getTokenResponse) // <------ accessTokenResponseClient is the default one
.onErrorMap(OAuth2AuthorizationException.class,
(e) -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e))
.map((tokenResponse) -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(),
tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()));
The workaround i found is to apply the configuration that should be used prior to 6.3 'Customize WebClient for OAuth2 Client (prior to 6.3') and publish a bean of type ReactiveOAuth2AuthorizedClientManager
I originally posted the issue on spring secutiry project https://github.com/spring-projects/spring-security/issues/15657 , but in fact it works when spring cloud gateway is not in the classpath. It may be related to https://github.com/spring-cloud/spring-cloud-gateway/issues/3493, but i'm not sure.