Spring Security 5 Calling OAuth2 Secured API in Application Runner results in IllegalArgumentException
Since I also stumbled across this problem I'll elaborate a bit on Darren Forsythe's updated answer to make it easier for others to find:
The issue submitted by the OP resulted in an implementation of OAuth2AuthorizedClientManager
that is capable of
operating outside of a HttpServletRequest context, e.g. in a scheduled/background thread and/or in the service-tier
(from the official docs)
Said implementation, the AuthorizedClientServiceOAuth2AuthorizedClientManager
, is passed to the ServletOAuth2AuthorizedClientExchangeFilterFunction
to replace the default one.
In my example this looks something like this:
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService clientService)
{
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistrationRepository, clientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager)
{
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(
authorizedClientManager);
oauth2.setDefaultClientRegistrationId("keycloak");
return WebClient.builder().apply(oauth2.oauth2Configuration()).build();
}
I ended up asking this to the Spring Security team,
https://github.com/spring-projects/spring-security/issues/6683
Unfortunately if you are on the servlet stack and calling to OAuth2 resources with pure Spring Security 5 APIs in a background thread there isn't a OAuth2AuthorizedClientRepository
available.
Realistically there's two options,
- Implement a completely no-op version,
var oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepo,
new OAuth2AuthorizedClientRepository() {
@Override
public <T extends OAuth2AuthorizedClient> T loadAuthorizedClient(String s,
Authentication authentication, HttpServletRequest httpServletRequest) {
return null;
}
@Override
public void saveAuthorizedClient(OAuth2AuthorizedClient oAuth2AuthorizedClient,
Authentication authentication, HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
}
@Override
public void removeAuthorizedClient(String s, Authentication authentication,
HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
}
});
- Implement a Servlet Version of
UnAuthenticatedServerOAuth2AuthorizedClientRepository
. UnAuthenticatedServerOAuth2AuthorizedClientRepository GitHub Source which has some basic functionality than a pure no-op.
Providing feedback on the GitHub issue might help the Spring Security team to evaluate accepting a PR and maintaining a Servlet version of the UnAuthenticatedServerOAuth2AuthorizedClientRepository
I reached out the the Spring Security Team Spring Security Issue 6683 and on the back of that a Servlet version of the ServerOAuth2AuthorizedClientExchangeFilterFunction
will be added in Spring Security 5.2 for usage on non-http threads.