D
D
Dmitry Belousov2020-04-13 20:38:15
JSON Web Token
Dmitry Belousov, 2020-04-13 20:38:15

Why can't login spring rest jwt?

Unable to log in, although registration is successful. Googled and someone wrote that the problem is that the password that came is not hashed, I try to hash it still does not work. I don't understand what the problem is. An exception is thrown and a 401 error is basically here:

authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            username,
                            password
                    )
            );

full controller code:
@RestController
@RequestMapping("/api/auth")
public class LoginController {

    @Autowired
    AuthenticationManager authenticationManager;

    Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    UserRepository userRepository;

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    JwtTokenProvider tokenProvider;

    @PostMapping("/signin")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        String username = loginRequest.getUserName();
        String password = passwordEncoder.encode(loginRequest.getPassword());
        Authentication authentication;
        try {
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            username,
                            password
                    )
            );
        } catch (AuthenticationException e) {
            logger.error("Invalid username/password supplied");
            throw new BadCredentialsException("Invalid username/password supplied");
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);

        String jwt = tokenProvider.generateToken(authentication);
        return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));

    }

    @PostMapping("/signup")
    public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
        if (userRepository.existsByUserName(signUpRequest.getUserName())) {
            return new ResponseEntity(new ApiResponse(false, "Username is already taken!"),
                    HttpStatus.BAD_REQUEST);
        }

        // Creating user's account
        Role userRole = roleRepository.findByRole(String.valueOf(RoleName.ROLE_USER))
                .orElseThrow(() -> new AppException("User Role not set."));

        User user = new User(signUpRequest.getUserName(), signUpRequest.getPassword(),
                signUpRequest.getName(), signUpRequest.getLastName(), signUpRequest.getMiddleName(), Collections.singleton(userRole));

        user.setPassword(passwordEncoder.encode(user.getPassword()));


        user.setRoles(Collections.singleton(userRole));

        User result = userRepository.save(user);

        URI location = ServletUriComponentsBuilder
                .fromCurrentContextPath().path("/users/{username}")
                .buildAndExpand(result.getUserName()).toUri();

        return ResponseEntity.created(location).body(new ApiResponse(true, "User registered successfully"));
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Belousov, 2020-04-14
@dreven

I solved the problem, it turns out that when I passed an object in the UserDetailsService method in the loadUserByUsername method, which was created based on UserDetails, I forgot to return objects in the username and password getters, and there is no need to send a hashed password. Everything is working.
Method:

@Override
    @Transactional
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {

        User user = userRepository.findByUserName(userName)
                .orElseThrow(() ->
                        new UsernameNotFoundException("User not found with username: " + userName)
                );
       UserPrincipal userPrincipal = UserPrincipal.create(user);
       logger.info("user with name: {} succesfully loaded", userPrincipal.getUsername());
       return userPrincipal;
    }

An object:
@Data
@Builder(toBuilder = true)
@NoArgsConstructor
public class UserPrincipal implements UserDetails {

    static Logger logger = LoggerFactory.getLogger(UserPrincipal.class);

    private Long id;

    private String name;

    private String username;

    private String lastname;

    private String middlename;

    private String password;

    private Collection<? extends GrantedAuthority> authorities;

    public UserPrincipal(Long id, String username, String name, String password, String lastname, String middlename, Collection<? extends GrantedAuthority> authorities) {
        this.id = id;
        this.name = name;
        this.username = username;
        this.lastname = lastname;
        this.middlename = middlename;
        this.password = password;
        this.authorities = authorities;

    }

    public static UserPrincipal create(User user) {
        logger.info(user.toString());
        List<GrantedAuthority> authorities = user.getRoles().stream().map(role ->
                new SimpleGrantedAuthority(role.getRole())
        ).collect(Collectors.toList());

        return new UserPrincipal(
                user.getId(),
                user.getUserName(),
                user.getName(),
                user.getPassword(),
                user.getLastName(),
                user.getMiddleName(),
                authorities
        );
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserPrincipal that = (UserPrincipal) o;
        return Objects.equals(id, that.id);
    }

    @Override
    public int hashCode() {

        return Objects.hash(id);
    }

@PostMapping("/signin")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        String username = loginRequest.getUserName();
        String password = loginRequest.getPassword();
        Authentication authentication;
        try {
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            username,
                            password
                    )
            );
        } catch (AuthenticationException e) {
            logger.error("Invalid username/password supplied");
            throw new BadCredentialsException("Invalid username/password supplied");
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);

        String jwt = tokenProvider.generateToken(authentication);
        return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));

    }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question