diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientConfigurations.java index 8d25fbc2e3..8eb3871b93 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientConfigurations.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientConfigurations.java @@ -28,7 +28,6 @@ import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2Clien import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.oauth2.client.InMemoryReactiveOAuth2AuthorizedClientService; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService; @@ -38,7 +37,6 @@ import org.springframework.security.oauth2.client.registration.ReactiveClientReg import org.springframework.security.oauth2.client.web.server.AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository; import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; import org.springframework.security.web.server.SecurityWebFilterChain; -import org.springframework.security.web.server.WebFilterChainProxy; import static org.springframework.security.config.Customizer.withDefaults; @@ -94,13 +92,6 @@ class ReactiveOAuth2ClientConfigurations { return http.build(); } - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(WebFilterChainProxy.class) - @EnableWebFluxSecurity - static class EnableWebFluxSecurityConfiguration { - - } - } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java index 31cb13aa60..5f5cba160e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java @@ -35,7 +35,6 @@ import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2Res import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity.OAuth2ResourceServerSpec; import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; @@ -50,7 +49,6 @@ import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.JwkSetUr import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder; import org.springframework.security.oauth2.jwt.SupplierReactiveJwtDecoder; import org.springframework.security.web.server.SecurityWebFilterChain; -import org.springframework.security.web.server.WebFilterChainProxy; import org.springframework.util.CollectionUtils; /** @@ -179,13 +177,6 @@ class ReactiveOAuth2ResourceServerJwkConfiguration { server.jwt((jwt) -> jwt.jwtDecoder(decoder)); } - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(WebFilterChainProxy.class) - @EnableWebFluxSecurity - static class EnableWebFluxSecurityConfiguration { - - } - } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java index dbeb778d87..f4d9614253 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java @@ -22,12 +22,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; import org.springframework.security.oauth2.server.resource.introspection.SpringReactiveOpaqueTokenIntrospector; import org.springframework.security.web.server.SecurityWebFilterChain; -import org.springframework.security.web.server.WebFilterChainProxy; import static org.springframework.security.config.Customizer.withDefaults; @@ -66,13 +64,6 @@ class ReactiveOAuth2ResourceServerOpaqueTokenConfiguration { return http.build(); } - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(WebFilterChainProxy.class) - @EnableWebFluxSecurity - static class EnableWebFluxSecurityConfiguration { - - } - } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java index 5bcb151be4..9e07d8f9b9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java @@ -17,21 +17,21 @@ package org.springframework.boot.autoconfigure.security.reactive; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.ReactiveAuthenticationManager; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.core.userdetails.ReactiveUserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.WebFilterChainProxy; import org.springframework.web.reactive.config.WebFluxConfigurer; @@ -52,33 +52,21 @@ import org.springframework.web.reactive.config.WebFluxConfigurer; @ConditionalOnClass({ Flux.class, EnableWebFluxSecurity.class, WebFilterChainProxy.class, WebFluxConfigurer.class }) public class ReactiveSecurityAutoConfiguration { - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(WebFilterChainProxy.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) - @Conditional(EnableWebFluxSecurityCondition.class) - @EnableWebFluxSecurity - static class EnableWebFluxSecurityConfiguration { + @Configuration(proxyBeanMethods = false) + class SpringBootWebFluxSecurityConfiguration { - } - - static final class EnableWebFluxSecurityCondition extends AnyNestedCondition { - - EnableWebFluxSecurityCondition() { - super(ConfigurationPhase.REGISTER_BEAN); + @Bean + @ConditionalOnMissingBean({ ReactiveAuthenticationManager.class, ReactiveUserDetailsService.class, + SecurityWebFilterChain.class }) + ReactiveAuthenticationManager denyAllAuthenticationManager() { + return (authentication) -> Mono.error(new UsernameNotFoundException(authentication.getName())); } - @ConditionalOnBean(ReactiveAuthenticationManager.class) - static final class ConditionalOnReactiveAuthenticationManagerBean { - - } - - @ConditionalOnBean(ReactiveUserDetailsService.class) - static final class ConditionalOnReactiveUserDetailsService { - - } - - @ConditionalOnBean(SecurityWebFilterChain.class) - static final class ConditionalOnSecurityWebFilterChain { + @Configuration(proxyBeanMethods = false) + @ConditionalOnMissingBean(WebFilterChainProxy.class) + @EnableWebFluxSecurity + static class EnableWebFluxSecurityConfiguration { } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java index 9583efcbc4..e8165ee189 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java @@ -740,6 +740,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { .isEqualTo("aud"); } + @EnableWebFluxSecurity static class TestConfig { @Bean @@ -781,7 +782,6 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { } - @EnableWebFluxSecurity @Configuration(proxyBeanMethods = false) static class SecurityWebFilterChainConfig { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java index dd5dd07ef3..006f7b228f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration.EnableWebFluxSecurityConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.context.annotation.Bean; @@ -53,28 +52,36 @@ class ReactiveSecurityAutoConfigurationTests { } @Test - void backsOffWhenReactiveAuthenticationManagerNotPresent() { + void autoConfiguresDenyAllReactiveAuthenticationManagerWhenNoAlternativeIsAvailable() { this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveSecurityAutoConfiguration.class) - .doesNotHaveBean(EnableWebFluxSecurityConfiguration.class)); + .hasBean("denyAllAuthenticationManager")); } @Test void enablesWebFluxSecurityWhenUserDetailsServiceIsPresent() { - this.contextRunner.withUserConfiguration(UserDetailsServiceConfiguration.class) - .run((context) -> assertThat(context).getBean(WebFilterChainProxy.class).isNotNull()); + this.contextRunner.withUserConfiguration(UserDetailsServiceConfiguration.class).run((context) -> { + assertThat(context).hasSingleBean(WebFilterChainProxy.class); + assertThat(context).doesNotHaveBean("denyAllAuthenticationManager"); + }); } @Test void enablesWebFluxSecurityWhenReactiveAuthenticationManagerIsPresent() { this.contextRunner .withBean(ReactiveAuthenticationManager.class, () -> mock(ReactiveAuthenticationManager.class)) - .run((context) -> assertThat(context).getBean(WebFilterChainProxy.class).isNotNull()); + .run((context) -> { + assertThat(context).hasSingleBean(WebFilterChainProxy.class); + assertThat(context).doesNotHaveBean("denyAllAuthenticationManager"); + }); } @Test void enablesWebFluxSecurityWhenSecurityWebFilterChainIsPresent() { this.contextRunner.withBean(SecurityWebFilterChain.class, () -> mock(SecurityWebFilterChain.class)) - .run((context) -> assertThat(context).getBean(WebFilterChainProxy.class).isNotNull()); + .run((context) -> { + assertThat(context).hasSingleBean(WebFilterChainProxy.class); + assertThat(context).doesNotHaveBean("denyAllAuthenticationManager"); + }); } @Test