Skip to content

Commit

Permalink
Making ReactiveUserDetailsServiceAutoConfiguration conditional
Browse files Browse the repository at this point in the history
The UserDetailsServiceAutoConfiguration is only to be active in a reactive web application

See gh-43345
  • Loading branch information
BenchmarkingBuffalo committed Dec 2, 2024
1 parent 4421fa4 commit e7b14f1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Expand All @@ -55,6 +56,7 @@
* {@link ReactiveAuthenticationManagerResolver}.
*
* @author Madhura Bhave
* @author Lasse Wulff
* @since 2.0.0
*/
@AutoConfiguration(before = ReactiveSecurityAutoConfiguration.class, after = RSocketMessagingAutoConfiguration.class)
Expand All @@ -65,6 +67,7 @@
type = { "org.springframework.security.oauth2.jwt.ReactiveJwtDecoder" })
@Conditional({ ReactiveUserDetailsServiceAutoConfiguration.RSocketEnabledOrReactiveWebApplication.class,
ReactiveUserDetailsServiceAutoConfiguration.MissingAlternativeOrUserPropertiesConfigured.class })
@ConditionalOnWebApplication(type = Type.REACTIVE)
@EnableConfigurationProperties(SecurityProperties.class)
public class ReactiveUserDetailsServiceAutoConfiguration {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.security.reactive;

import java.time.Duration;
import java.util.function.Function;

import org.junit.jupiter.api.Test;

Expand All @@ -28,6 +29,7 @@
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
Expand All @@ -52,12 +54,36 @@
*
* @author Madhura Bhave
* @author HaiTao Zhang
* @author Lasse Wulff
*/
class ReactiveUserDetailsServiceAutoConfigurationTests {

private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ReactiveUserDetailsServiceAutoConfiguration.class));

@Test
void shouldSupplyUserDetailsServiceInReactiveApp() {
this.contextRunner.withUserConfiguration(TestSecurityConfiguration.class)
.with(AuthenticationExclude.reactiveApp())
.run((context) -> assertThat(context).hasSingleBean(ReactiveUserDetailsService.class));
}

@Test
void shouldNotSupplyUserDetailsServiceInServletApp() {
new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ReactiveUserDetailsServiceAutoConfiguration.class))
.with(AuthenticationExclude.servletApp())
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveUserDetailsService.class));
}

@Test
void shouldNotSupplyUserDetailsServiceInNonWebApp() {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ReactiveUserDetailsServiceAutoConfiguration.class))
.with(AuthenticationExclude.noWebApp())
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveUserDetailsService.class));
}

@Test
void configuresADefaultUser() {
this.contextRunner
Expand All @@ -72,7 +98,7 @@ void configuresADefaultUser() {

@Test
void userDetailsServiceWhenRSocketConfigured() {
new ApplicationContextRunner()
this.contextRunner
.withClassLoader(
new FilteredClassLoader(ClientRegistrationRepository.class, ReactiveOpaqueTokenIntrospector.class))
.withConfiguration(AutoConfigurations.of(ReactiveUserDetailsServiceAutoConfiguration.class,
Expand All @@ -98,7 +124,7 @@ void doesNotConfigureDefaultUserIfUserDetailsServiceAvailable() {
void doesNotConfigureDefaultUserIfAuthenticationManagerAvailable() {
this.contextRunner.withUserConfiguration(AuthenticationManagerConfig.class, TestSecurityConfiguration.class)
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class))
.run((context) -> assertThat(context).getBean(ReactiveUserDetailsService.class).isNull());
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveUserDetailsService.class));
}

@Test
Expand Down Expand Up @@ -175,6 +201,25 @@ private void testPasswordEncoding(Class<?> configClass, String providedPassword,
}));
}

private static final class AuthenticationExclude {

private static final FilteredClassLoader filteredClassLoader = new FilteredClassLoader(
ClientRegistrationRepository.class, ReactiveOpaqueTokenIntrospector.class);

static Function<WebApplicationContextRunner, WebApplicationContextRunner> servletApp() {
return (contextRunner) -> contextRunner.withClassLoader(filteredClassLoader);
}

static Function<ReactiveWebApplicationContextRunner, ReactiveWebApplicationContextRunner> reactiveApp() {
return (contextRunner) -> contextRunner.withClassLoader(filteredClassLoader);
}

static Function<ApplicationContextRunner, ApplicationContextRunner> noWebApp() {
return (contextRunner) -> contextRunner.withClassLoader(filteredClassLoader);
}

}

@Configuration(proxyBeanMethods = false)
@EnableWebFluxSecurity
@EnableConfigurationProperties(SecurityProperties.class)
Expand Down

0 comments on commit e7b14f1

Please sign in to comment.