Describe the bug version - spring boot 3.0.1 - spring security 6.0.1

not execute .permitAll() just not registered controller.

To Reproduce Spring Security requestMatchers does not execute .permitAll() for not registered Bean requestMatchers dose not execute .permitAll(). localhost:8080/data request response is 403 forbidden. ("/data" URL is not mvcMatcher, not registered controller API)

Spring Security requestMatchers does not execute .permitAll() for not registered Bean but, all include matcher ("/**") execute .permitAll().

Expected behavior

    .authorizeHttpRequests(authorize -> authorize
            .requestMatchers("/data").permitAll()
    )

localhost:8080/data request expected 404 Not Found;

Comment From: rnjsrntkd95

I checked spring boot 2.7.1 version is execute normally to use antMatcher.

Comment From: marcusdacoregio

Hi @rnjsrntkd95,

is your security configuration class annotated with @EnableWebSecurity and @Configuration? If it is, can you share a minimal, reproducible sample so we simulate it on our side?

Comment From: rnjsrntkd95

of course! this is my public repository

security-request-matcher-issue

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers(
                "/favicon.ico", "/health.html", "/robots.txt"
        );
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .csrf().disable()
                .formLogin().disable()
                .logout().disable()
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/data").permitAll()    // this response is 403 forbidden, expect 404 Not Found because set permitAll
//                        .requestMatchers("/**").permitAll()     // if you release this comment, "/data" response is 404 Not Found
                )
                .authorizeHttpRequests().anyRequest().authenticated()
                .and().build();
    }
}

It's the same if I use an antMatcher not mvcMatcher.

.requestMatchers(antMatcher("/data")).permitAll()

Comment From: rnjsrntkd95

but, if declare like this. "/data" request execute normally .permitAll . It is 200 Ok.

@RestController
public class TestController {

    @GetMapping("/data")
    public String data() {
        return "test";
    }
}

I guess... .permitAll() works only with declared controller. as registered bean. is this mvcMatcher role?

In the same way, WebSecurity.ignoring needs authenticate but i set ignored filter

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers(
                "/favicon.ico"
        );
    }

AuthenticationEntryPoint commence() catch this exception

InsufficientAuthenticationException: Full authentication is required to access this resource

Comment From: rnjsrntkd95

I found the cause.

Error page ("/error") is created about 404 by request "/data" but, I didn't handled error page. processed authorizeHttpRequests default denied. I solved this issue by "/error" .permitAll or .ignoring()

Debugging through this annotation @EnableWebSecurity(debug = true)

this is my mistake. thank u @marcusdacoregio It you have any advice, comment please!

Comment From: marcusdacoregio

It you have any advice, comment please!

In your dev environment, it is good to set the logging level of Spring Security to TRACE, this way you can debug faster what is happening in the filter chain. To do that change your application.properties to include:

logging.level.org.springframework.security=TRACE

Glad you figured it out!

Comment From: WuzorGiftKnowledge

I found the cause.

Error page ("/error") is created about 404 by request "/data" but, I didn't handled error page. processed authorizeHttpRequests default denied. I solved this issue by "/error" .permitAll or .ignoring()

Debugging through this annotation @EnableWebSecurity(debug = true)

this is my mistake. thank u @marcusdacoregio It you have any advice, comment please!

this saved me after many hours. thank you

Comment From: gokul656

Hi @rnjsrntkd95,

is your security configuration class annotated with @EnableWebSecurity and @Configuration? If it is, can you share a minimal, reproducible sample so we simulate it on our side?

Thanks, it worked for me.

Comment From: hongwenchina

Thanks, it worked for me and saved me many hours

Comment From: hongwenchina

I found the cause.

Error page ("/error") is created about 404 by request "/data" but, I didn't handled error page. processed authorizeHttpRequests default denied. I solved this issue by "/error" .permitAll or .ignoring()

Debugging through this annotation @EnableWebSecurity(debug = true)

this is my mistake. thank u @marcusdacoregio It you have any advice, comment please!

Thanks, it worked for me and saved me many hours

Comment From: thiago123789

I found the cause.

Error page ("/error") is created about 404 by request "/data" but, I didn't handled error page. processed authorizeHttpRequests default denied. I solved this issue by "/error" .permitAll or .ignoring()

Debugging through this annotation @EnableWebSecurity(debug = true)

this is my mistake. thank u @marcusdacoregio It you have any advice, comment please!

This saved my day, thanks!! After some hours struggling to understand why was not working :D

Comment From: chrisegb

Hi, I still have the problem. Please find below my example:

@Configuration
@EnableWebSecurity(debug = true)
@RequiredArgsConstructor
public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final AuthenticationProvider authenticationProvider;

    private static final String[] AUTH_WHITELIST = {
            "/rmnd/api/accesses/**"
    };

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity.csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers(AUTH_WHITELIST)
                        .permitAll()
                        .anyRequest()
                        .authenticated())
                .sessionManagement((session) -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/error");
    }
}

Second way I was trying:

package com.memry.memry.security.configuration;

import com.memry.memry.security.filters.JwtAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity(debug = true)
@RequiredArgsConstructor
public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final AuthenticationProvider authenticationProvider;

    private static final String[] AUTH_WHITELIST = {
            "/rmnd/api/accesses/**",
            "/error"
    };

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity.csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers(AUTH_WHITELIST)
                        .permitAll()
                        .anyRequest()
                        .authenticated())
                .sessionManagement((session) -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }
}

Both are returning 403:

{
    "timestamp": "2023-12-13T16:40:43.040+00:00",
    "status": 403,
    "error": "Forbidden",
    "message": "Access Denied",
    "path": "/rmnd/api/accesses/log-in"
}

@rnjsrntkd95 any ideas why I'm still getting the 403? Maybe you have something else?

Comment From: kat-lin

Hi, @chrisegb

Did you get it to work? For me works when I add .dispatcherTypeMatchers(FORWARD, ERROR).permitAll() before .requestMatchers("/...").permitAll()

See Spring Security docs.

An example code:

        @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http.sessionManagement((session) -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(reqs -> reqs
                        .dispatcherTypeMatchers(FORWARD, ERROR).permitAll()
                        .requestMatchers("/api/v1/test").permitAll()
                        .anyRequest().authenticated())
                .formLogin(Customizer.withDefaults())
                .httpBasic(Customizer.withDefaults())
                .csrf(AbstractHttpConfigurer::disable)
                .build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/api/v1/users");
    }

Happy New Year!

Comment From: Aschay

Well I have the same issue and only websecuritycustomizer seems to be working allows certain url

@Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/whitelisturl");
}

Comment From: pavelhoodie

In my case, the following worked:

.requestMatchers("/", "index.html").permitAll()

I just had to write the file's extention :)