Hi!
I just updated several services to SpringBoot 2.1.3 and observed a different behavior regarding integration tests in WebFlux and WebMVC in combination with spring-security.
In both services a custom SecurityConfig exists.
In the WebMVC service the config looks like:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// custom config is here
}
}
In the WebFlux service the config looks like:
@Configuration
@EnableWebFluxSecurity
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
//custom config is here
}
}
When implementing an integration test using @WebMvcTest the custom WebSecurityConfig is called (placing a breakpoint in the configure method works). But in order to be active it is necessary to callapply(SecurityMockMvcConfigurers.springSecurity()) on the MockMvcBuilder.
I think this is in line with the documentation provided here:
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#test-mockmvc-setup
When implementing an integration test using @WebFluxTest the custom SecurityConfiguration is not called, but instead the standard org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration is used. I have to use @Import on the test class to get the custom SecurityConfiguration to work.
I couldn't find anything in the documentation that describes this behavior of @WebFluxTest. I would expect that @WebFluxTest behaves like @WebMvcTest and uses the custom SecurityConfiguration.
Comment From: dkroehan
Related to: https://github.com/spring-projects/spring-boot/issues/6514
Comment From: mbhave
@dkroehan @WebFluxTest should pick up the custom security configuration. Can you provide a minimal sample that we can run to reproduce the issue?
Comment From: dkroehan
@mbhave I added a sample application here: https://github.com/dkroehan/webfluxtest
Comment From: snicoll
@dkroehan your Webflux security does not inherit from ServerHttpSecurity so we can't detect it (notice that the MVC counterpart is extending from Spring Security's base class).
Comment From: dkroehan
@snicoll Is this documented anywhere?
I checked spring-security docs: https://docs.spring.io/autorepo/docs/spring-security/current/reference/htmlsingle/#minimal-webflux-security-configuration https://docs.spring.io/autorepo/docs/spring-security/current/reference/htmlsingle/#test-webflux
and the Javadoc: https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.html https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/web/server/ServerHttpSecurity.html
None of these examples shows this.
Comment From: wilkinsona
your Webflux security does not inherit from ServerHttpSecurity
I don't think it should. The ServerHttpSecurity bean is provided by Spring Security, not a user's application.
Comment From: snicoll
🤷♂️
Comment From: mbhave
@wilkinsona is right. This is a bug in WebFluxTypeExcludeFilter. It should include SecurityWebFilterChain beans rather than ServerHttpSecurity.
Comment From: mbhave
Actually, the problem is broader than just fixing the type in WebFluxTypeExcludeFilter. WebFluxTypeExcludeFilter only applies to beans created by component scanning. When you have something like this:
@Configuration
@EnableWebFluxSecurity
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
//custom config is here
}
}
The WebFluxTypeExcludeFilter doesn't include @Configuration classes and SecurityWebFilterChain which is not created by component scanning doesn't get picked up.
@dkroehan As a workaround, you could add @Import(SecurityConfiguration.class) in the test class.
Comment From: mbhave
We discussed this and it would be quite a big change for 2.1.x. We'll document the limitation for now.
Comment From: kevhussey
@mbhave - Thank you for this. I also ran into this problem. I finally got my test to work by adding
@Import(SecurityConfig.class)
@WithMockUser
on class level.
Comment From: brnhffmnn
@mbhave this issue seems stale. Is there any progress or other workaround that doesn't require to adjust all my test classes?
Comment From: wilkinsona
This has come up again recently. I wonder if we can do something in 2.7 or early in the 2.6.x maintenance releases?