I am new with spring security and trying to implement basic authentication on a spring boot rest service.I am using database based authentication and have User and Role table.When i make request any controller in my app with right credentials it gives me always 403 forbidden.I can't figure why.I check the role many times it is correct.And in database role names are "USER" and "RESTAURANT" and "ADMIN".I tried both with ROLE_ prefix and standalone uppercase syntax either way didn't work.Don't know what am i doing wrong.Here is my configuration class:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled=true,jsr250Enabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private UserDetailsService customUserDetailsService;
@Autowired
private AuthenticationEntryPoint authEntryPoint;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception
{
auth.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.httpBasic()
.authenticationEntryPoint(authEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/user/register","/forgotPassword").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
;
}
}
Here is my UserDetailService implementation:
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
User user = userRepository.findByUsername(username);
System.out.println(user.toString()); //here i check if it's finding right user
if (user == null) {
throw new UsernameNotFoundException(username +" not found");
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user));
}
private static Collection<? extends GrantedAuthority> getAuthorities(User user)
{
String[] userRoles = user.getRoles()
.stream()
.map((role) -> role.getName())
.toArray(String[]::new);
Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(userRoles);
return authorities;
}
}
And this is the one of my controllers that returns 403:
@PreAuthorize("hasRole('USER')")
//@Secured("USER")
@GetMapping("/{restaurantmenu}") //bütün menüyü çeker
Collection<Menu> getMenu(@PathVariable("restaurantmenu") Long id) {
return menuService.getMenuItemsByRestaurant(restaurantService.getRestaurant(id));
}
And for your info. i have a registration url so ı take new User via json and register it into database with encrypted (Bcrypt) password and i am trying to authenticate with that.I am able to retrieve new user and register to db and correctly encrypt password. I don't know if i will be able to control username and email while registration with this way but if you care here's the responding controller method :
@RestController
@RequestMapping(value="/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
void registerUser(@Valid @RequestBody User user) {
userService.save(user);
}
}
Every help and advice will be preciated.