javaspringhttpspring-security

How to configure Spring Security to allow GET method for everyone and restrict other methods to specific roles without much boilerplate?


what I want to do is, to permit all user to make GET requests to /product, but for any of the other methods like POST, DELETE and so on, I want them to have admin or user role.

Is there a way to permit get and request role for the other without writing so many lines of code? or do I need to specify each HTTP Method individually like I've done below?

authorizeConfig.requestMatchers(HttpMethod.GET,"/product").permitAll();
authorizeConfig.requestMatchers(HttpMethod.POST,"/product").hasAnyRole("admin", "user");
authorizeConfig.requestMatchers(HttpMethod.DELETE,"/product").hasAnyRole("admin", "user");

For reference this is my securityFilterChain Bean:

 @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(
                        authorizeConfig -> {
                            authorizeConfig.requestMatchers("/").permitAll();
                            authorizeConfig.requestMatchers(HttpMethod.GET,"/product").permitAll();
                            authorizeConfig.requestMatchers(HttpMethod.POST,"/product").hasAnyRole("admin", "user");
                            authorizeConfig.requestMatchers("/protected").hasRole("admin");
                            authorizeConfig.requestMatchers("/userinfo").hasRole("user");
                            authorizeConfig.anyRequest().authenticated();
                        })
                .oauth2Login(Customizer.withDefaults())
                .oauth2ResourceServer(config -> {
                    config.jwt(Customizer.withDefaults());
                })
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                .build();
    }

I'm using java 21 with spring boot 3.2.3.


Solution

  • You're on the right track with your current configuration. There's a way to achieve what you want without specifying each HTTP method individually in Spring Security.

    Here's how:

    authorizeConfig.antMatchers(HttpMethod.GET, "/product").permitAll()
             .antMatchers("/product/**").hasAnyRole("admin", "user")
             .anyRequest().authenticated();
    

    With this configuration, users can access the /product endpoint with a GET request without needing a role. However, any other HTTP method on /product or its sub-paths requires the user to have either the "admin" or "user" role.