From 3e00fef5828f6a7deadda912bcd30ac618fa7fc5 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Tue, 10 Nov 2020 15:01:00 -0500 Subject: [PATCH] Moves ReactiveOAuth2AuthorizedClientManager to its own autoconfig This allows auto configuration order to be followed without worrying about the TokenRelayGatewayFilterFactory. --- .../config/GatewayAutoConfiguration.java | 18 ------ ...atewayReactiveOAuth2AutoConfiguration.java | 58 +++++++++++++++++++ .../TokenRelayGatewayFilterFactory.java | 4 +- .../main/resources/META-INF/spring.factories | 3 +- .../config/GatewayAutoConfigurationTests.java | 4 +- 5 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveOAuth2AutoConfiguration.java 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 0cd71d7d..e338588a 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 @@ -152,11 +152,6 @@ import org.springframework.core.env.Environment; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; -import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; -import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -853,19 +848,6 @@ public class GatewayAutoConfiguration { return new TokenRelayGatewayFilterFactory(clientManager); } - @Bean - @ConditionalOnBean(ReactiveClientRegistrationRepository.class) - public ReactiveOAuth2AuthorizedClientManager gatewayReactiveOAuth2AuthorizedClientManager( - ReactiveClientRegistrationRepository clientRegistrationRepository, - ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder - .builder().authorizationCode().refreshToken().build(); - DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( - clientRegistrationRepository, authorizedClientRepository); - authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); - return authorizedClientManager; - } - } } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveOAuth2AutoConfiguration.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveOAuth2AutoConfiguration.java new file mode 100644 index 00000000..45ecb48c --- /dev/null +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveOAuth2AutoConfiguration.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.gateway.config; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; +import org.springframework.cloud.gateway.config.conditional.ConditionalOnEnabledFilter; +import org.springframework.cloud.gateway.filter.factory.TokenRelayGatewayFilterFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; +import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; +import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true) +@ConditionalOnClass({ OAuth2AuthorizedClient.class, SecurityWebFilterChain.class, SecurityProperties.class }) +@ConditionalOnEnabledFilter(TokenRelayGatewayFilterFactory.class) +@AutoConfigureAfter(ReactiveSecurityAutoConfiguration.class) +public class GatewayReactiveOAuth2AutoConfiguration { + + @Bean + @ConditionalOnBean(ReactiveClientRegistrationRepository.class) + public ReactiveOAuth2AuthorizedClientManager gatewayReactiveOAuth2AuthorizedClientManager( + ReactiveClientRegistrationRepository clientRegistrationRepository, + ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().refreshToken().build(); + DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( + clientRegistrationRepository, authorizedClientRepository); + authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); + return authorizedClientManager; + } + +} 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 8923f8ff..dba205cb 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 @@ -62,8 +62,8 @@ public class TokenRelayGatewayFilterFactory extends AbstractGatewayFilterFactory .principal(oauth2Authentication).build(); ReactiveOAuth2AuthorizedClientManager clientManager = clientManagerProvider.getIfAvailable(); if (clientManager == null) { - return Mono.error( - new IllegalStateException("No ReactiveOAuth2AuthorizedClientManager bean was found. Did you include the " + 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? diff --git a/spring-cloud-gateway-server/src/main/resources/META-INF/spring.factories b/spring-cloud-gateway-server/src/main/resources/META-INF/spring.factories index 989a1afb..4904d259 100644 --- a/spring-cloud-gateway-server/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-gateway-server/src/main/resources/META-INF/spring.factories @@ -8,7 +8,8 @@ org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\ org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration,\ org.springframework.cloud.gateway.config.SimpleUrlHandlerMappingGlobalCorsAutoConfiguration,\ -org.springframework.cloud.gateway.config.GatewayReactiveLoadBalancerClientAutoConfiguration +org.springframework.cloud.gateway.config.GatewayReactiveLoadBalancerClientAutoConfiguration,\ +org.springframework.cloud.gateway.config.GatewayReactiveOAuth2AutoConfiguration org.springframework.boot.env.EnvironmentPostProcessor=\ org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor \ No newline at end of file diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java index 5f7f65e2..0247578a 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java @@ -151,10 +151,10 @@ public class GatewayAutoConfigurationTests { } @Test - public void metricsBeansAreCreated() { + public void tokenRelayBeansAreCreated() { new ReactiveWebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class, - ReactiveOAuth2ClientAutoConfiguration.class, + ReactiveOAuth2ClientAutoConfiguration.class, GatewayReactiveOAuth2AutoConfiguration.class, GatewayAutoConfiguration.TokenRelayConfiguration.class)) .withPropertyValues( "spring.security.oauth2.client.provider[testprovider].authorization-uri=http://localhost",