spring-security icon indicating copy to clipboard operation
spring-security copied to clipboard

Fix Customizer.withDefaults() for authorizeHttpRequests

Open manueljordan opened this issue 2 years ago • 3 comments

For Spring Boot 3.1.6 with Spring Security where the respective version used behind the scene is 6.1.5

Consider the following code:

@Configuration
@Profile("security")
@EnableWebSecurity(debug=true)
class SecurityConfig {

  	...

	@Bean
	SecurityFilterChain filterChain(HttpSecurity http,
                                    @Qualifier("inspectorFilter") Filter filter) throws Exception {
		http.authorizeHttpRequests(Customizer.withDefaults())
	  	       .formLogin(Customizer.withDefaults())
	  	       .addFilterBefore(filter, AnonymousAuthenticationFilter.class);
		return http.build();
	}

}

Observe the authorizeHttpRequests and formLogin methods use Customizer.withDefaults() when the app starts well, it does not start but fails with the following error message:

[           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: 
 org.springframework.beans.factory.UnsatisfiedDependencyException: 
  Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': 
   Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: 
    Error creating bean with name 'filterChain' defined in class path resource [com/manuel/jordan/config/SecurityConfig.class]: 
	 Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: 
	  Factory method 'filterChain' threw exception with message: 
	   At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())
...
org.springframework.beans.factory.UnsatisfiedDependencyException: 
 Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': 
  Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: 
   Error creating bean with name 'filterChain' defined in class path resource [com/manuel/jordan/config/SecurityConfig.class]: 
    Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: 
	 Factory method 'filterChain' threw exception with message: 
	  At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())
	   at
...
Caused by: org.springframework.beans.factory.BeanCreationException: 
 Error creating bean with name 'filterChain' defined in class path resource [com/manuel/jordan/config/SecurityConfig.class]: 
  Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: 
   Factory method 'filterChain' threw exception with message: 
    At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())
	 at
...
Caused by: org.springframework.beans.BeanInstantiationException: 
 Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: 
  Factory method 'filterChain' threw exception with message: 
   At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())
	at
...
Caused by: java.lang.IllegalStateException: At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())
	at	 

The solution is change:

  • from http.authorizeHttpRequests(Customizer.withDefaults())
  • to http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())

It as indicated in the error stack trace.

I am not sure if it is expected, but if not - Fix Customizer.withDefaults() for authorizeHttpRequests

Thanks for your understanding

  • Manuel

manueljordan avatar Dec 18 '23 17:12 manueljordan

Hi, @manueljordan. This behavior is expected as you pointed out that the stack trace says:

At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())

Spring Boot configures it to require authentication for every request, however, if you override it, you have to specify what are your authorization rules as Spring Security would not know what would be a proper default for your application.

marcusdacoregio avatar Dec 18 '23 18:12 marcusdacoregio

Hi @marcusdacoregio

It is confuse in someway. So why from the beginning the default behavior is not authorizeHttpRequests().anyRequest().authenticated()?

manueljordan avatar Dec 18 '23 22:12 manueljordan

Good point, @manueljordan. We recommend users be explicit about their security configuration, especially when dealing with request authorization. However, if we have a default for everything it makes sense to have a default for that too. The ServerHttpSecurity#authorizeExchange allows us to use Customizer.withDefaults() and considers the DelegatingReactiveAuthorizationManager defaults, which is to deny all. I will bring this to the team's attention and decide how we move forward.

marcusdacoregio avatar Dec 19 '23 17:12 marcusdacoregio