次のコードが与えられた場合、アプリケーションランナーでクライアント資格情報で保護されたAPIを呼び出すことは可能ですか?
@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);
}
};
}
次の理由でコードが失敗します。
Java.lang.IllegalArgumentException: request cannot be null
フルスタック、
Java.lang.IllegalArgumentException: request cannot be null
at org.springframework.util.Assert.notNull(Assert.Java:198) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizedClientRepository.loadAuthorizedClient(HttpSessionOAuth2AuthorizedClientRepository.Java:47) ~[spring-security-oauth2-client-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.populateDefaultOAuth2AuthorizedClient(ServletOAuth2AuthorizedClientExchangeFilterFunction.Java:364) ~[spring-security-oauth2-client-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.lambda$null$2(ServletOAuth2AuthorizedClientExchangeFilterFunction.Java:209) ~[spring-security-oauth2-client-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.attributes(DefaultWebClient.Java:234) ~[spring-webflux-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.attributes(DefaultWebClient.Java:153) ~[spring-webflux-5.1.5.RELEASE.jar:5.1.5.RELEASE]
失敗したメソッドは次のようになります。
public <T extends OAuth2AuthorizedClient> T loadAuthorizedClient(
String clientRegistrationId, Authentication principal, HttpServletRequest request){
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
Assert.notNull(request, "request cannot be null");
return (OAuth2AuthorizedClient)this
.getAuthorizedClients(request)
.get(clientRegistrationId);
}
使用するHttpServletRequest
がないため、これは理にかなっています。アプリケーションの起動時に呼び出されます。
自分でno-opOAuth2AuthorizedClientRepository
を作成する以外の回避策はありますか?
//編集、
これは完全にリアクティブなスタックではありません。これは、WebClientが使用されているSpringWebスタックです。
完全にリアクティブなスタックに適用され、サーブレットスタック上に構築されたアプリケーションにあるために使用できないReactiveClientRegistrationRepository
とServerOAuth2AuthorizedClientExchangeFilterFunction
を必要とするReactiveOauth2AuthorizedClient
をよく知っています。反応しません。
私もこの問題に遭遇したので、他の人が見つけやすくするために Darren Forsythe's 更新された回答について少し詳しく説明します。
OPによって提出された問題により、次のことが可能なOAuth2AuthorizedClientManager
が実装されました。
httpServletRequestコンテキストの外部で動作します。スケジュールされた/バックグラウンドスレッドおよび/またはサービス層で
( 公式ドキュメントから )
この実装であるAuthorizedClientServiceOAuth2AuthorizedClientManager
は、デフォルトの実装を置き換えるためにServletOAuth2AuthorizedClientExchangeFilterFunction
に渡されます。
私の例では、これは次のようになります。
@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();
}
私はこれをSpringSecurityチームに尋ねることになりました。
https://github.com/spring-projects/spring-security/issues/668
残念ながら、サーブレットスタックを使用していて、バックグラウンドスレッドで純粋なSpring Security 5 APIを使用してOAuth2リソースを呼び出す場合、利用可能なOAuth2AuthorizedClientRepository
はありません。
現実的には2つのオプションがあります。
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) { } });
UnAuthenticatedServerOAuth2AuthorizedClientRepository
を実装します。 nAuthenticatedServerOAuth2AuthorizedClientRepository GitHub Source これは純粋なno-opよりもいくつかの基本的な機能を備えています。GitHubの問題に関するフィードバックを提供すると、Spring SecurityチームがPRの受け入れと、サーブレットバージョンのUnAuthenticatedServerOAuth2AuthorizedClientRepository
の維持を評価するのに役立つ場合があります。
Spring Securityチームに連絡しました Spring Security Issue 668 そして、その後ろにServerOAuth2AuthorizedClientExchangeFilterFunction
のサーブレットバージョンがSpringSecurity 5.2に追加され、http以外のスレッドで使用できるようになります。