-1

A Spring UserDetailsService contains an admin with role ADMIN and an user with role USER:

@Bean
public UserDetailsService uds() {
    UserDetails admin = User.builder()
        .username("admin")
        .password(encoder().encode("pwa"))
        .roles("ADMIN")
        .build();
    UserDetails user = User.builder()
        .username("user")
        .password(encoder().encode("pwu"))
        .roles("USER")
        .build();
    return new InMemoryUserDetailsManager(admin, user);
}

The repository extends CrudRepository

@RepositoryRestResource
public interface CountryRepo extends CrudRepository<Country, Long> { }

where POST requests map to the save method.

The SecurityFilterChain requires POST requests to be sent by clients with ADMIN role (see (*)):

@Bean
SecurityFilterChain configureSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(authCustomizer -> authCustomizer
            .requestMatchers("/api/countries").permitAll()
            .requestMatchers("/h2").permitAll()
            .requestMatchers(HttpMethod.POST, "/api/countries").hasRole("ADMIN")  // <-- (*)
            .anyRequest().authenticated()
        )
        .csrf().disable()
        .httpBasic(withDefaults());
    http.headers().frameOptions().disable();
    return http.build();
}

csrf and frameOptions are needed to use the H2 console in the browser.

An admin can create countries with CURL:

C:\Users\project>curl -H "Content-Type: application/json" -u admin:pwa -X POST http://localhost:8080/api/countries -d "{\"countryCode\":\"AUS\"}"
{
  "countryCode" : "AUS",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/countries/4"
    },
    "country" : {
      "href" : "http://localhost:8080/api/countries/4"
    }
  }
}

However, so can a user! I expected to get a 401 or 403 HTTP status code here.

C:\Users\mahed>curl -H "Content-Type: application/json" -u user:pwu -X POST http://localhost:8080/api/countries -d "{\"countryCode\":\"CAN\"}"
{
  "countryCode" : "CAN",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/countries/5"
    },
    "country" : {
      "href" : "http://localhost:8080/api/countries/5"
    }
  }
}

Why are the POST requests by user, who does not have the ADMIN role, successful?

TMOTTM
  • 3,286
  • 6
  • 32
  • 63

1 Answers1

0

The requestMatcher matching the POST request needs to be before the general requestMatcher. This filter chain works:

@Bean
SecurityFilterChain configureSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(authCustomizer -> authCustomizer
            .requestMatchers(HttpMethod.POST, "/api/countries").hasRole("ADMIN")
            .requestMatchers("/api/countries").permitAll()
            .requestMatchers("/h2").permitAll()
            .anyRequest().authenticated()
        )
        .csrf().disable()
        .httpBasic(withDefaults());
    http.headers().frameOptions().disable();
    return http.build();
}
TMOTTM
  • 3,286
  • 6
  • 32
  • 63