1

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.

Berk Altuğ
  • 47
  • 2
  • 12

1 Answers1

0

Saving Roles as ROLE_USER, ROLE_ADMIN in the database and Adding a particular method might help you.

.antMatchers(HttpMethod.POST,"/user/register","/forgotPassword").permitAll()
.antMatchers(HttpMethod.GET,"/restaurantURL").permitAll()

EDIT: Refer this to get more details on Roles

Romil Patel
  • 12,879
  • 7
  • 47
  • 76
  • It actually worked ! Thanks mate i only saved roles with ROLE_ prefix and worked but i wonder why it has to be that way ? Why spring security couldn't resolve only role name ? – Berk Altuğ Feb 26 '19 at 08:34