diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration.java index 37cd4d36fc..c2f4ce2a73 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration.java @@ -37,6 +37,7 @@ import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; import org.springframework.security.authentication.ReactiveAuthenticationManager; +import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver; import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; import org.springframework.security.core.userdetails.ReactiveUserDetailsService; import org.springframework.security.core.userdetails.User; @@ -48,14 +49,17 @@ import org.springframework.util.StringUtils; * Default user {@link Configuration @Configuration} for a reactive web application. * Configures a {@link ReactiveUserDetailsService} with a default user and generated * password. This backs-off completely if there is a bean of type - * {@link ReactiveUserDetailsService} or {@link ReactiveAuthenticationManager}. + * {@link ReactiveUserDetailsService}, {@link ReactiveAuthenticationManager}, or + * {@link ReactiveAuthenticationManagerResolver}. * * @author Madhura Bhave * @since 2.0.0 */ @AutoConfiguration(after = RSocketMessagingAutoConfiguration.class) @ConditionalOnClass({ ReactiveAuthenticationManager.class }) -@ConditionalOnMissingBean(value = { ReactiveAuthenticationManager.class, ReactiveUserDetailsService.class }, +@ConditionalOnMissingBean( + value = { ReactiveAuthenticationManager.class, ReactiveUserDetailsService.class, + ReactiveAuthenticationManagerResolver.class }, type = { "org.springframework.security.oauth2.jwt.ReactiveJwtDecoder", "org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector" }) @Conditional(ReactiveUserDetailsServiceAutoConfiguration.ReactiveUserDetailsServiceCondition.class) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfigurationTests.java index 50eea54462..31b350ccc5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2022 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. @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.security.authentication.ReactiveAuthenticationManager; +import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver; import org.springframework.security.config.annotation.rsocket.EnableRSocketSecurity; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; @@ -91,6 +92,13 @@ class ReactiveUserDetailsServiceAutoConfigurationTests { .run((context) -> assertThat(context).getBean(ReactiveUserDetailsService.class).isNull()); } + @Test + void doesNotConfigureDefaultUserIfAuthenticationManagerResolverAvailable() { + this.contextRunner.withUserConfiguration(AuthenticationManagerResolverConfig.class) + .run((context) -> assertThat(context).hasSingleBean(ReactiveAuthenticationManagerResolver.class) + .doesNotHaveBean(ReactiveUserDetailsService.class)); + } + @Test void doesNotConfigureDefaultUserIfResourceServerWithJWTIsUsed() { this.contextRunner.withUserConfiguration(JwtDecoderConfiguration.class).run((context) -> { @@ -179,6 +187,16 @@ class ReactiveUserDetailsServiceAutoConfigurationTests { } + @Configuration(proxyBeanMethods = false) + static class AuthenticationManagerResolverConfig { + + @Bean + ReactiveAuthenticationManagerResolver reactiveAuthenticationManagerResolver() { + return mock(ReactiveAuthenticationManagerResolver.class); + } + + } + @Configuration(proxyBeanMethods = false) @Import(TestSecurityConfiguration.class) static class TestConfigWithPasswordEncoder {