With the introduction of OAuth2AuthorizedClientManager in Spring Security 5.2, it's possibly to handle the authorization of OAuth2 clients with HTTP clients or abstractions other than WebClient.
We could use something like
OAuth2AuthorizedClient authorizedClient = authorizedClientManager.authorize(
OAuth2AuthorizeRequest
.withClientRegistrationId("registration-id")
.principal("client-id")
.build()
);
Reference: https://github.com/spring-projects/spring-security/issues/8018#issuecomment-601183465
Although I can now get an access token from the OAuth2AuthorizedClient (e.g. String accessToken = authorizedClient.getAccessToken().getTokenValue()), I must always first call authorizedClientManager.authorize(oAuth2AuthorizeRequest) to ensure that I have a valid access token before calling a downstream service. If the access token is expired, the authorize call will perform a Client Credentials call to the token endpoint and get a response back with a fresh token. However, if my microservice receives multiple calls at the same time (e.g. on different request threads), the authorize call could theoretically call the token endpoint for every request thread because each request thread will determine that the access token is expired and request a new one before calling the downstream service. Only once the the OAuth2AuthorizedClientRepository is updated with a valid token, will the request threads stop invoking more token endpoint calls. Also, there may be a flurry of token endpoint responses that will overwrite each other with the final response's access token getting persisted in the the repository until the next expiration.
I'd like to find a way to efficiently authorize client credentials clients in a multithreaded context so that I don't trigger a race condition of token requests. The only ways around this that I can think of is to schedule authorizations before the access token expires or for Spring Security to prevent multiple token endpoint calls if it's waiting for the first response.
Any suggestions would be greatly appreciated.