I'm trying to create a Spring Boot REST application that has to make a remote REST call to another application protected by OAuth2.
The first application is using the Reactive WebClient to make the call to the second OAuth2 REST application. I've configured the WebClient
with grant_type "client_credentials".
application.yml
spring:
security:
oauth2:
client:
provider:
client-registration-id:
token-uri: http://localhost:8080/oauth/token
registration:
client-registration-id:
authorization-grant-type: client_credentials
client-id: public
client-secret: test
client-authentication-method: post
scope: myscope
@Configuration
public class WebClientConfig {
@Bean
WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
oauth.setDefaultClientRegistrationId("client-registration-id");
return WebClient.builder().filter(oauth).build();
}
}
@Component
public class WebClientChronJob {
Logger logger = LoggerFactory.getLogger(WebClientChronJob.class);
@Autowired
private WebClient webClient;
@Scheduled(fixedRate = 5000)
public void logResourceServiceResponse() {
webClient.get()
.uri("http://localhost:8080/test")
.retrieve()
.bodyToMono(String.class)
.map(string -> "RESPONSE: " + string)
.subscribe(logger::info);
}
}
According to the article at Baeldung Spring Webclient Oauth2, the second time that WebClientChronJob
runs, the application should request the resource without asking for a token first since the last one hasn't expired. Unfortunately, enabling the debug logs, I noticed the opposite: each time the job requests the resource it's asking for a new token. Please let me know if something is missing in configuration or code.
Netty started on port(s): 8082
Started MyApp in 2.242 seconds (JVM running for 2.717)
HTTP POST http://localhost:8080/oauth/token
Writing form fields [grant_type, scope, client_id, client_secret] (content masked)
Response 200 OK
Decoded [{access_token=nrLr7bHpV0aqr5cQNhv0NjJYvVv3bv, token_type=Bearer, expires_in=86400, scope=rw:profile (truncated)...]
Cancel signal (to close connection)
HTTP GET http://localhost:8080/test
Response 200 OK
Decoded "{"status":{"description":"ok","success":true},"result":[]}"
ESPONSE: {"status":{"description":"ok","success":true},"result":[]}
HTTP POST http://localhost:8080/oauth/token
Writing form fields [grant_type, scope, client_id, client_secret] (content masked)
Response 200 OK
Decoded [{access_token=CsOxziw6W6J7IoqA8EiF4clhiwVJ8m, token_type=Bearer, expires_in=86400, scope=rw:profile (truncated)...]
Cancel signal (to close connection)
HTTP GET http://localhost:8080/test
Response 200 OK
Decoded "{"status":{"description":"ok","success":true},"result":[]}"
ESPONSE: {"status":{"description":"ok","success":true},"result":[]}
Below the only dependencies I have in the pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>