I want to enable admin to access admin page and do admin stuff, but when I try to do that by setting that the url with /admin/** can only be accessed by user with role admin, it returns 403 Forbidden, access denied. But the user has authorities set to ROLE_ADMIN I checked. What am I doing wrong?
My Controller for user login
@RestController
public class UserController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthorityService authorityService;
@Autowired
private UserAuthorityService userAuthorityService;
@Autowired
TokenUtils tokenUtils;
@Autowired
private UserService userService;
@RequestMapping(value = "/api/login", method = RequestMethod.POST, produces = "text/html")
public ResponseEntity<String> login(@RequestBody LoginDTO loginDTO) {
try {
// System.out.println(loginDTO.getUsername() + " " + loginDTO.getPassword());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
loginDTO.getUsername(), loginDTO.getPassword());
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails details = userDetailsService.loadUserByUsername(loginDTO.getUsername());
return new ResponseEntity<String>(tokenUtils.generateToken(details), HttpStatus.OK);
} catch (Exception ex) {
return new ResponseEntity<String>("Invalid login", HttpStatus.BAD_REQUEST);
}
}
@RequestMapping(value = "/api/register", method = RequestMethod.POST, produces = "text/html")
public ResponseEntity<String> register(@RequestBody RegisterDTO registerDTO) {
try {
System.out.println(registerDTO);
User user = userService.findUserByUsername(registerDTO.getUsername());
// // Check if user with that username exists
if(user != null){
// User with that username is found
return new ResponseEntity<String>("User with that username exists", HttpStatus.BAD_REQUEST);
}
// We need to save the user so his ID is generated
User newUser = userService.saveUser(new User(registerDTO));
UserAuthority userAuthority = userAuthorityService.save(new UserAuthority(newUser, authorityService.findOneByName("User")));
Set<UserAuthority> authorities = new HashSet<>();
authorities.add(userAuthority);
newUser.setUserAuthorities(authorities);
User savedUser = userService.save(newUser);
return new ResponseEntity<String>("You have registered successfully with username " + savedUser.getUsername(), HttpStatus.OK);
} catch (Exception ex) {
return new ResponseEntity<String>("Invalid register", HttpStatus.BAD_REQUEST);
}
}
}
I can say that I test my app with postman and login and registration are working fine. When the user is logged in I can the token with the correct data and users authorities, but why when I try to access /admin/building/add url it is returning 403 error?
My Controller for adding building for admin page:
@RestController
public class BuildingController {
@Autowired
private BuildingService buildingService;
@RequestMapping(value = "/admin/building/add", method = RequestMethod.POST, produces = "text/html")
public ResponseEntity<String> addBuilding(@RequestBody BuildingDTO buildingDTO) {
try{
Building newBuilding = new Building(buildingDTO);
return new ResponseEntity<String>(newBuilding.getName(), HttpStatus.OK);
}catch (Exception ex) {
return new ResponseEntity<String>("Data was not valid", HttpStatus.BAD_REQUEST);
}
}
}
My SecurityConfiguration.java
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public void configureAuthentication(
AuthenticationManagerBuilder authenticationManagerBuilder)
throws Exception {
authenticationManagerBuilder
.userDetailsService(this.userDetailsService).passwordEncoder(
passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public AuthenticationTokenFilter authenticationTokenFilterBean()
throws Exception {
AuthenticationTokenFilter authenticationTokenFilter = new AuthenticationTokenFilter();
authenticationTokenFilter
.setAuthenticationManager(authenticationManagerBean());
return authenticationTokenFilter;
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/index.html", "/view/**", "/app/**", "/", "/api/login", "/api/register").permitAll()
// defined Admin only API area
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest()
.authenticated()
.and().csrf().disable();
//if we use AngularJS on client side
// .and().csrf().csrfTokenRepository(csrfTokenRepository());
//add filter for adding CSRF token in the request
httpSecurity.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
// Custom JWT based authentication
httpSecurity.addFilterBefore(authenticationTokenFilterBean(),
UsernamePasswordAuthenticationFilter.class);
}
/**
* If we use AngularJS as a client application, it will send CSRF token using
* name X-XSRF token. We have to tell Spring to expect this name instead of
* X-CSRF-TOKEN (which is default one)
* @return
*/
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
I should mention that I am using Angularjs for frontend, but even so I can login and the correct authorities are displayed for that user. But for some reason I can not access the admin page, even if I login as admin.
Also I tried .hasAuthority("ROLE_ADMIN")
and .hasRole("ROLE_ADMIN")
(which displays an error for ROLE_) and so I changed it to .hasRole("ADMIN")
but it is still not working.
In the database the role for admin is saved as ROLE_ADMIN.