The following logic does not look correct
The username extracted from token and the one coming from userDetails will always be the same. Why is it comparing the two?
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) &&
!isTokenExpired(token));
}
}