I am facing the issue which is not obvious to resolve just by reading the documentation. While migrating to Spring Boot v2.7.4 / Spring Security v5.7.3 I have refactored the configuration not to extend WebSecurityConfigurerAdapter
and to look like below:
@Configuration
@EnableWebSecurity
public class CustomSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.
csrf().disable().
logout().disable().
authorizeRequests().anyRequest().permitAll();
return http.build();
}
}
The above method is called, however has no effect as SecurityFilterChain
instance created by OAuth2SecurityFilterChainConfiguration
is used instead (I see that from debug by inspecting the list of filter in the stack that has e.g. LogoutFilter
which should be disabled by above configuration). Debug log:
2022-10-20 15:49:48.790 [main] o.s.b.a.s.DefaultWebSecurityCondition : Condition DefaultWebSecurityCondition on org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwtConfiguration$OAuth2SecurityFilterChainConfiguration matched due to AllNestedConditions 2 matched 0 did not; NestedCondition on DefaultWebSecurityCondition.Beans @ConditionalOnMissingBean (types: org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter,org.springframework.security.web.SecurityFilterChain; SearchStrategy: all) did not find any beans; NestedCondition on DefaultWebSecurityCondition.Classes @ConditionalOnClass found required classes 'org.springframework.security.web.SecurityFilterChain', 'org.springframework.security.config.annotation.web.builders.HttpSecurity'
2022-10-20 15:49:48.791 [main] a.ConfigurationClassBeanDefinitionReader : Registered bean definition for imported class 'org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwtConfiguration$OAuth2SecurityFilterChainConfiguration'
2022-10-20 15:49:48.792 [main] o.s.b.a.condition.OnBeanCondition : Condition OnBeanCondition on org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwtConfiguration$OAuth2SecurityFilterChainConfiguration#jwtSecurityFilterChain matched due to @ConditionalOnBean (types: org.springframework.security.oauth2.jwt.JwtDecoder; SearchStrategy: all) found bean 'jwtDecoderByJwkKeySetUri'
...
2022-10-20 15:49:49.082 [main] a.ConfigurationClassBeanDefinitionReader : Registering bean definition for @Bean method com.mycompany.CustomSecurityConfig.filterChain()
...
2022-10-20 15:49:52.276 [main] edFilterInvocationSecurityMetadataSource : Adding web access control expression [authenticated] for any request
2022-10-20 15:50:13.348 [main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@33502cfe, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@729d1428, org.springframework.security.web.context.SecurityContextPersistenceFilter@7d0312a, org.springframework.security.web.header.HeaderWriterFilter@6ca97ddf, org.springframework.security.web.csrf.CsrfFilter@38f569d, org.springframework.security.web.authentication.logout.LogoutFilter@1104ad6a, org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter@74ab8610, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7833407, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@66acaa54, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@115924ba, org.springframework.security.web.session.SessionManagementFilter@6a905513, org.springframework.security.web.access.ExceptionTranslationFilter@5749e633, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@49741e80]
...
2022-10-20 15:50:13.384 [main] edFilterInvocationSecurityMetadataSource : Adding web access control expression [permitAll] for any request
2022-10-20 15:50:17.641 [main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@4a0f4282, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@19d3f4fb, org.springframework.security.web.context.SecurityContextPersistenceFilter@99f75e4, org.springframework.security.web.header.HeaderWriterFilter@118c1faa, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@2b6ff016, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5aefdb9e, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@43cf97a8, org.springframework.security.web.session.SessionManagementFilter@da5b46f, org.springframework.security.web.access.ExceptionTranslationFilter@11267e87, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@7827cdfc]
Is it expected that the bean CustomSecurityConfig.filterChain
participates in DefaultWebSecurityCondition
evaluation and OAuth2SecurityFilterChainConfiguration.jwtSecurityFilterChain
is not created. Or the issue with DefaultWebSecurityCondition
is that the instance of WebSecurityConfigurerAdapter
is not in the context anymore (as to issue #10822 it is deprecated)?
The suggestion to add @Order()
annotation didn't work:
@Configuration
@EnableWebSecurity
public class CustomSecurityConfig {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { ...
as well as further attempts to exclude the autoconfiguration class like this:
@SpringBootApplication(excludeName = "org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwtConfiguration.OAuth2SecurityFilterChainConfiguration")
public class Application extends SpringBootServletInitializer { ...
failed probably due to issue #5427 with the following error
java.lang.IllegalStateException: The following classes could not be excluded because they are not auto-configuration classes:
- org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwtConfiguration.OAuth2SecurityFilterChainConfiguration
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.handleInvalidExcludes(AutoConfigurationImportSelector.java:222) ~[spring-boot-autoconfigure-2.7.4.jar!/:2.7.4]
This way also does not work:
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*OAuth2ResourceServerJwtConfiguration.*")})
public class Application extends SpringBootServletInitializer { ...
The documentation I read before posting:
- Spring Security without the WebSecurityConfigurerAdapter
- Spring Security: Upgrading the Deprecated WebSecurityConfigurerAdapter
- Spring Security - How to Fix WebSecurityConfigurerAdapter Deprecated
Update
I have created a small Maven project that demonstrates the issue. After project is started, request the controller like this:
$ wget -nv -O - 'http://localhost:8080/spring/test'
Username/Password Authentication Failed.
As one can see, the custom configured SecurityFilterChain
is not active because otherwise the access would be granted (as to antMatchers( "/**/test").permitAll()
). ContextRefreshedEvent
listener dumps two SecurityFilterChain
instances (jwtSecurityFilterChain
and filterChain
), the priority of them is not possible to configure reliably.