From 8722f4062ed21de28ebf56f69bccc5ad4ac1d29d Mon Sep 17 00:00:00 2001 From: spencergibb Date: Tue, 10 Nov 2020 12:57:11 -0500 Subject: [PATCH] Makes dependencies of TokenRelayGatewayFilterFactory lazy. Because of the use in the java dsl before oauth2 client auto configuration can run, the ReactiveOAuth2AuthorizedClientManager field of TokenRelayGatewayFilterFactory needs to be lazy. --- .../gateway/config/GatewayAutoConfiguration.java | 4 ++-- .../factory/TokenRelayGatewayFilterFactory.java | 13 ++++++++++--- .../TokenRelayGatewayFilterFactoryTests.java | 6 +++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index dc158736..0cd71d7d 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -845,16 +845,16 @@ public class GatewayAutoConfiguration { @ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true) @ConditionalOnClass({ OAuth2AuthorizedClient.class, SecurityWebFilterChain.class, SecurityProperties.class }) @ConditionalOnEnabledFilter(TokenRelayGatewayFilterFactory.class) - @ConditionalOnBean(ReactiveClientRegistrationRepository.class) protected static class TokenRelayConfiguration { @Bean public TokenRelayGatewayFilterFactory tokenRelayGatewayFilterFactory( - ReactiveOAuth2AuthorizedClientManager clientManager) { + ObjectProvider clientManager) { return new TokenRelayGatewayFilterFactory(clientManager); } @Bean + @ConditionalOnBean(ReactiveClientRegistrationRepository.class) public ReactiveOAuth2AuthorizedClientManager gatewayReactiveOAuth2AuthorizedClientManager( ReactiveClientRegistrationRepository clientRegistrationRepository, ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactory.java index 23f34b46..8923f8ff 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactory.java @@ -18,6 +18,7 @@ package org.springframework.cloud.gateway.filter.factory; import reactor.core.publisher.Mono; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; @@ -31,11 +32,11 @@ import org.springframework.web.server.ServerWebExchange; */ public class TokenRelayGatewayFilterFactory extends AbstractGatewayFilterFactory { - private final ReactiveOAuth2AuthorizedClientManager clientManager; + private final ObjectProvider clientManagerProvider; - public TokenRelayGatewayFilterFactory(ReactiveOAuth2AuthorizedClientManager clientManager) { + public TokenRelayGatewayFilterFactory(ObjectProvider clientManagerProvider) { super(Object.class); - this.clientManager = clientManager; + this.clientManagerProvider = clientManagerProvider; } public GatewayFilter apply() { @@ -59,6 +60,12 @@ public class TokenRelayGatewayFilterFactory extends AbstractGatewayFilterFactory String clientRegistrationId = oauth2Authentication.getAuthorizedClientRegistrationId(); OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistrationId) .principal(oauth2Authentication).build(); + ReactiveOAuth2AuthorizedClientManager clientManager = clientManagerProvider.getIfAvailable(); + if (clientManager == null) { + return Mono.error( + new IllegalStateException("No ReactiveOAuth2AuthorizedClientManager bean was found. Did you include the " + + "org.springframework.boot:spring-boot-starter-oauth2-client dependency?")); + } // TODO: use Mono.defer() for request above? return clientManager.authorize(request); } diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactoryTests.java index 5029cc42..fa3af966 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/TokenRelayGatewayFilterFactoryTests.java @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.HttpHeaders; @@ -69,6 +70,7 @@ public class TokenRelayGatewayFilterFactoryTests { } @Before + @SuppressWarnings("unchecked") public void init() { request = MockServerHttpRequest.get("/hello").build(); mockExchange = MockServerWebExchange.from(request); @@ -76,7 +78,9 @@ public class TokenRelayGatewayFilterFactoryTests { when(filterChain.filter(any(ServerWebExchange.class))).thenReturn(Mono.empty()); authorizedClientManager = mock(ReactiveOAuth2AuthorizedClientManager.class); - filter = new TokenRelayGatewayFilterFactory(authorizedClientManager).apply(); + ObjectProvider objectProvider = mock(ObjectProvider.class); + when(objectProvider.getIfAvailable()).thenReturn(authorizedClientManager); + filter = new TokenRelayGatewayFilterFactory(objectProvider).apply(); } @After