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?
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.
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.
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:
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));
Alternatively, you can use hasAuthority("User")
instead:
// ...
.antMatchers("/employee", "/insurance").hasAuthority("User")
// ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With