Description
Summary
Currently there is a way to auto-wire OAuth2AuthorizedClientService in a component in the service/data tier to lookup the OAuth2AuthorizedClient. This works, but you would still need to use OAuth2AuthorizedClientArgumentResolver to resolve OAuth2AuthorizedClient in web-tier first. My suggestion is to make things more self-contained in service/data tier by allowing OAuth2AuthorizedClientService to get new access tokens if needed. I think Spring should allow new access tokens to be retrieved either way (in service/data tier OR web tier). We tried this with a custom service bean and it is working using some of the logic in OAuth2AuthorizedClientArgumentResolver.
Example
Here is an example of a bean that could be created and used by OAuth2AuthorizedClientArgumentResolver (in the web tier) OR used by a class in the service/data tier to get new access tokens. This also has a temporary workaround to get around #6609 (where access token is never refreshed).
public class OAuth2AuthorizedClientService {
private ClientRegistrationRepository clientRegistrationRepository;
private OAuth2AuthorizedClientRepository authorizedClientRepository;
private HttpServletRequest httpServletRequest;
private HttpServletResponse httpServletResponse;
private DefaultClientCredentialsTokenResponseClient defaultClientCredentialsTokenResponseClient = new DefaultClientCredentialsTokenResponseClient();
public OAuth2AuthorizedClientService(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository,
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClientRepository = authorizedClientRepository;
this.httpServletRequest = httpServletRequest;
this.httpServletResponse = httpServletResponse;
}
public OAuth2AuthorizedClient getAuthorizedClient(String audience) {
Authentication principal = SecurityContextHolder.getContext().getAuthentication();
ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(audience);
OAuth2AuthorizedClient authorizedClient = this.authorizedClientRepository.loadAuthorizedClient(
audience, principal, httpServletRequest);
if (authorizedClient != null && authorizedClient.getAccessToken().getExpiresAt().isAfter(Instant.now().plusSeconds(300))) {
return authorizedClient;
}
OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest =
new OAuth2ClientCredentialsGrantRequest(clientRegistration);
defaultClientCredentialsTokenResponseClient
.setRequestEntityConverter(new Auth0ClientCredentialsGrantRequestEntityConverter(
audience));
OAuth2AccessTokenResponse tokenResponse =
defaultClientCredentialsTokenResponseClient.getTokenResponse(clientCredentialsGrantRequest);
authorizedClient = new OAuth2AuthorizedClient(
clientRegistration,
principal.getName(),
tokenResponse.getAccessToken());
this.authorizedClientRepository.saveAuthorizedClient(
authorizedClient,
principal,
httpServletRequest,
httpServletResponse);
return authorizedClient;
}
public void setDefaultClientCredentialsTokenResponseClient(DefaultClientCredentialsTokenResponseClient defaultClientCredentialsTokenResponseClient) {
this.defaultClientCredentialsTokenResponseClient = defaultClientCredentialsTokenResponseClient;
}
}