spring-bootspring-securityjava-security

@PreAuthorize("hasAuthority('String')") not working expectedly


I have created the Spring Security configuration as it's below:

@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/Login").permitAll()
                .anyRequest().authenticated()
                .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
            .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

And each user has their own role/authority as of this:

public enum TypeEnum implements GrantedAuthority {
    CUSTOMER("Customer"),
    
    EMPLOYEE("Employee");

    private String value;

    TypeEnum(String value) {
      this.value = value;
    }

    @Override
    @JsonValue
    public String toString() {
      return String.valueOf(value);
    }

    @JsonCreator
    public static TypeEnum fromValue(String text) {
      for (TypeEnum b : TypeEnum.values()) {
        if (String.valueOf(b.value).equals(text)) {
          return b;
        }
      }
      return null;
    }

    @Override
    public String getAuthority() {
      return name();

In my controller I am trying to pre-authorize it with certain roles

@PreAuthorize("hasAuthority('Employee')")
public ResponseEntity<List<User>> getUsers(@Parameter(in = ParameterIn.QUERY, description = "Get user that corresponds to userID"
        ,schema=@Schema()) @Valid @RequestParam(value = "userid", required = false) Integer userid,
                                           @Parameter(in = ParameterIn.QUERY, description = "Get user that has account with IBAN" ,
                                                   schema=@Schema()) @Valid @RequestParam(value = "iban", required = false) Integer iban,
                                           @Parameter(in = ParameterIn.QUERY, description = "Get users based on Last Name" ,
                                                   schema=@Schema()) @Valid @RequestParam(value = "lastname", required = false) String lastname,
                                           @Parameter(in = ParameterIn.QUERY, description = "Maximum numbers of items to return" ,
                                                   schema=@Schema()) @Valid @RequestParam(value = "limit", required = false) Integer limit)
{
    return new ResponseEntity<List<User>>(userService.getAllUser(), HttpStatus.OK);
}

I printed the getAuthorities method

System.out.println(SecurityContextHolder.getContext().getAuthentication().getAuthorities());

Which resulting in Customer

When I try to access the endpoint, it still shows the results and give status 200.


Solution

  • I think you should add @EnableGlobalMethodSecurity(prePostEnabled = true) annotation to your security config to be able to use hasAuthority() method.

    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfigurer extends WebSecurityConfigurerAdapter{
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            
           http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/Login").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
           http
                .addFilterBefore(jwtRequestFilter, 
                                 UsernamePasswordAuthenticationFilter.class);
        }
    
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws 
                                                                 Exception {
            return super.authenticationManagerBean();
        }
    }