Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP 403 forbidden error in spring boot security

Spring security configuration class

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .cors()
            .and()
            .authorizeRequests()
            .antMatchers("/user", "/login").permitAll()
            .antMatchers("/employee", "/insurance").hasRole("User")
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic()
            .and()
            .csrf().disable();
    }

    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
    }
}

UserDetailsService Implementation class

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        User user = null;
        Set<GrantedAuthority> grantedAuthorities = null;
        try
        {
            user = userService.findByUserName(userName);
            if(user == null)
                throw new UsernameNotFoundException("User " + userName  + " not available");

            grantedAuthorities = new HashSet<>();
            for(Role role: user.getRoles()) {
                grantedAuthorities.add(new SimpleGrantedAuthority(role.getRole().toString()));
            }
        }
        catch(Exception exp) {
            exp.printStackTrace();
        }
        return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(), grantedAuthorities);
    }
}

Employee Rest Controller class

@RestController
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private InsuranceService insuranceService;

    @PostMapping("/employee")
    public ResponseEntity<Employee> create(@RequestBody Employee employee) throws Exception {
        employee = employeeService.create(employee);
        return new ResponseEntity<Employee>(employee, HttpStatus.CREATED);
    }

    @PutMapping("/employee")
    public ResponseEntity<Employee> update(@RequestBody Employee employee) throws Exception {
        employee = employeeService.update(employee);
        return new ResponseEntity<Employee>(employee, HttpStatus.OK);
    }

    @DeleteMapping("/employee/{id}")
    public ResponseEntity<String> delete(@PathVariable("id") long id) throws Exception {
        employeeService.delete(id);
        return new ResponseEntity<String>("Employee deleted successfully", HttpStatus.OK);
    }

    @GetMapping("/employee/{id}")
    public ResponseEntity<Employee> findEmployeeDetails(@PathVariable("id") long id) throws Exception {
        Employee employee = employeeService.findById(id);
        return new ResponseEntity<Employee>(employee, HttpStatus.OK);
    }

    @GetMapping("/employee")
    public ResponseEntity<List<Employee>> findAll() throws Exception {
        List<Employee> employees = employeeService.findAll();
        return new ResponseEntity<List<Employee>>(employees, HttpStatus.OK);
    }
}

I am getting 403 forbidden error for any of the HTTP method(POST/GET/PUT) request submitted via postman to /employee URL

{
    "timestamp": "2019-09-17T05:37:35.778+0000",
    "status": 403,
    "error": "Forbidden",
    "message": "Forbidden",
    "path": "/hr-core/employee"
}

I am getting this error even though I am sending correct username & password in the basic auth header(Authorization) of HTTP request in POSTMAN. This user is also having both USER and ADMIN roles to access /employee REST endpoint. I have disabled CSRF in http security.

How can I solve this error?

like image 958
Karthik Avatar asked Sep 17 '19 06:09

Karthik


People also ask

How does Spring Security handle 403 Forbidden error?

Simply disabling CSRF on your configure method with http. csrf(). disable(); is all that needed to be done for my put requests to stop receiving 403. Save this answer.

What is the meaning of HTTP 403 forbidden?

The HTTP 403 Forbidden response status code indicates that the server understands the request but refuses to authorize it. This status is similar to 401 , but for the 403 Forbidden status code, re-authenticating makes no difference.


1 Answers

Within Spring Security, there is a difference between roles and authorities. While an authority can be anything, roles are a subset of authorities that start with ROLE_.

Let's say you have the following authorities:

GrantedAuthority authority1 = new SimpleGrantedAuthority("User");
GrantedAuthority authority2 = new SimpleGrantedAuthority("ROLE_Admin");

In this case, authority1 does not contain a role, while authority2 does because it's prefixed with ROLE_.

That means, that if you use hasRole("User"), you won't have access, because it's not defined as a role. hasRole("Admin") on the other hand would work.

To solve this, you have two options:

  1. Make sure your roles are really prefixed with ROLE_. If you don't store them that way in your database, you can modify your UserDetailsServiceImpl:

    String roleName = "ROLE_" + role.getRole().toString();
    grantedAuthorities.add(new SimpleGrantedAuthority(roleName));
    
  2. Alternatively, you can use hasAuthority("User") instead:

    // ...
    .antMatchers("/employee", "/insurance").hasAuthority("User")
    // ...
    
like image 66
g00glen00b Avatar answered Nov 19 '22 05:11

g00glen00b