We have a Springboot application (let’s say microservice-A) and there is a requirement that we should add a HTTP Authorisation header with the OAuth2 token to access one of our other microservice (let’s say microservice-B). Also we are said that we can retreive this OAuth2 token by sending a HTTP POST request with Grant_type, Scope and basic authentication username and password to the same microservice-B.
Now my doubt is, do we have any kind of out of the box support from Spring security to automatically retrieve this OAuth2 token from microservice-B whenever it expires and send the subsequent HTTP requests. Or is this not required at all and I should just retrieve the OAuth2 token first by sending a normal HTTP POST request from microservice-A and then send the subsequent requests. (This way I might have to retrieve the OAuth2 token every time I want to send a request or save the token and retrieve it when it expires)
Microservice-A is the “client" Microservice-B is the “resource server”
Found a solution using org.springframework.boot:spring-boot-starter-oauth2-client
. Below are the configurations required to configure a OAUTH2 based WebClient that can automatically fetch the OAUTH2 token from auth-server (Microservice-B) and access resource-server (Microservice-B).
application.properties
oauth2.client.registration.pgw.scope=all
oauth2.client.registration.pgw.client-id=client
oauth2.client.registration.pgw.client-secret=secret
oauth2.client.provider.pgw.token-uri=http://localhost:8082/oauth/token
Oauth2ClientConfiguration.java
@Configuration
public class Oauth2ClientConfiguration {
@Bean
public ReactiveClientRegistrationRepository getRegistration(
@Value("${oauth2.client.provider.pgw.token-uri}") String tokenUri,
@Value("${oauth2.client.registration.pgw.client-id}") String clientId,
@Value("${oauth2.client.registration.pgw.client-secret}") String clientSecret,
@Value("${oauth2.client.registration.pgw.scope}") String scope) {
ClientRegistration registration = ClientRegistration
.withRegistrationId(OAUTH2_CLIENT_REGISTRATION_ID)
.tokenUri(tokenUri)
.clientId(clientId)
.clientSecret(clientSecret)
.authorizationGrantType(CLIENT_CREDENTIALS)
.scope(scope)
.build();
return new InMemoryReactiveClientRegistrationRepository(registration);
}
@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
InMemoryReactiveOAuth2AuthorizedClientService clientService =
new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrations);
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(clientRegistrations, clientService);
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth.setDefaultClientRegistrationId(OAUTH2_CLIENT_REGISTRATION_ID);
return WebClient.builder().filter(oauth).build();
}
}
Then we can access use this WebClient bean to send HTTP request to resource-server which will take care of fetching and managing the OAUTH2 token
webClient.get().uri("http://localhost:8080/api/private").retrieve().bodyToMono(String.class).block();