I was going through the Spring Security Oauth 2.x migration to Spring security 5.2 and encountered the following blocker.
As I can see OAuth2RestTemplate
is not used anymore, instead WebClient
is recommended. So i was making changes to my codebase to make webclient work.
In Oauth2 we have an option to get token straight from RestTemplate using oAuth2RestTemplate.getAccessToken()
, i couldn't find anything similar in WebClient. This is to call an external microservice.
Is there any option to get the accesstoken from webclient? Or is it handled in a different way there?
As usual when working with spring security, a lot of stuff happens automagically with configuration by convention. Meaning: you should get familiar with the oauth-related spring security configuration.
A good starting point for your studies will be the spring security docu or one of the many good Baeldung articles on this topic (maybe this one helps: https://www.baeldung.com/spring-oauth-login-webflux).
With the correct configuration in place, the following method will create a WebClient
that has the proper oauth token automatically created on demand in the filter method.
In this case a Bean of type ReactiveOAuth2AuthorizedClientManager
takes care of this. That bean is created in listing no. 2.
Furthermore, you need to configure the oauth server url and the credentials. See Listing 3 for a simple example.
This example works without you needing to handle the access token.
@Bean
public WebClient oauthWebClient(
final WebClient.Builder webClientBuilder,
@Qualifier("authorizedClientManager") final ReactiveOAuth2AuthorizedClientManager manager) {
final ExchangeStrategies exchangeStrategies =
ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(EXCHANGE_BYTE_COUNT))
.build();
final ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(manager);
oauth.setDefaultClientRegistrationId(authenticationProperties.getClientId());
// set more properties if needed
// oauth.set ...
return webClientBuilder
.exchangeStrategies(exchangeStrategies)
.baseUrl(apiProperties.getBaseUrl())
.filter(oauth)
.build();
}
Listing 1: create a WebClient bean
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
final ReactiveClientRegistrationRepository clientRegistrationRepository,
final ReactiveOAuth2AuthorizedClientService authorizedClientService) {
final ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder
.builder()
.clientCredentials()
.build();
final AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
Listing 2: create an OAuth2 authorized client manager bean
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://your-oauth-server.com/auth/realms/your-realm
client:
provider:
your-provider:
issuer-uri: https://your-oauth-server.com/auth/realms/your-realm
registration:
your-provider:
client-id: your-client-id
client-secret: ${your_client_secret} # from an environment variable
scope: openid
authorization-grant-type: client_credentials
Listing 3: one of many possible ways to configure your spring web client