Description
Summary
Currently when Using ServletOAuth2AuthorizedClientExchangeFilterFunction
(this might also apply to the Server impl) this requires a OAuth2AuthorizedClientRepository`.
This work fine when there is a some sort of request in progress however when calling to OAuth2 secured resources when no web request is in progress each will fail.
A user can provide their own no-op impl such as,
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) {
}
});
However this doesn't lend itself to be easily undersood why, and any use use to call OAuth2 secured resources without an HttpServlet Request/Response will need it. Across mutiple apps this can get messy.
Actual Behavior
Provide no-op implementations of the OAuth2AuthorizedClientRepository
to allow easier discovery/documentation for use cases that exist for calling secured OAuth2 resources outside of a web request.
Expected Behavior
OAuth2 Resource call does not require users to impl their own no-op impl. Spring Security provides class to allow easier documentation of use cases for no-op impls. .
Configuration
Example failure impl,
@Bean
public ApplicationRunner test(WebClient.Builder builder,
ClientRegistrationRepository clientRegistrationRepo, OAuth2AuthorizedClientRepository authorizedClient) {
return args -> {
try {
var oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepo,
authorizedClient);
oauth2.setDefaultClientRegistrationId("test");
var response = builder.apply(oauth2.oauth2Configuration()).build().get()
.uri("test").retrieve()
.bodyToMono(String.class).block();
log.info("Response - {}", response);
} catch (Exception e) {
log.error("Failed to call test.", e);
}
};
}
Working impl,
@Bean
public ApplicationRunner test(WebClient.Builder builder,
ClientRegistrationRepository clientRegistrationRepo, OAuth2AuthorizedClientRepository authorizedClient) {
return args -> {
try {
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) {
}
});
oauth2.setDefaultClientRegistrationId("test");
var response = builder.apply(oauth2.oauth2Configuration()).build().get()
.uri("test").retrieve()
.bodyToMono(String.class).block();
log.info("Response - {}", response);
} catch (Exception e) {
log.error("Failed to call test.", e);
}
};
}
Version
Spring Boot 2.1.3, Spring Security 5.1.3