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?