6

In spring security, UserDetails uses username as an identifier of user. My user model have multiple types of identifications and have multiple ways of authentication (via email, phone number, facebook, etc).

I am using AuthorizationServerEndpointsConfigurer to configure my oauth2 endpoints. JdbcTokenStore stores user_name in database, and what I need to store is userId. I already changed the JdbcTokenStore to fill my needs, but I am not understanding why spring framework makes the assumption that the username is the unique identifier, my app does not even use usernames.

For example, in TokenStore inferface findTokensByClientIdAndUserName is based in username, why not findTokensByClientIdAndUserId? If I authenticate the user with email or phone number, how can I get all tokens for that user?

My user model example: id, email, phone number, facebook_id, name. Email, phone number and facebook id are optional, only one of them are required. In this case what is the best candidate for username? Should I use user id as an username in spring way of abstraction?

André Abreu
  • 737
  • 7
  • 13

1 Answers1

6

Not sure if I understood the whole question but will try to give my best explanation for UserDetailService. UserDetailsService's method loadByUsername is just a method which allows you to retrieve the user from your database and compare it with the credentials from the request from the client to see if it is an existing user or non existing one. Although the name of the method is loadUserByUsername, it doesn't mean that you must literally pass a username, you can pass it any argument like email, phone number or whatever you authentication is based on.

Here is an example implementation for that service, where I identify my users by calling the database through UserRepository and giving it as an argument email.

@Service
public class CustomUserDetailsService implements UserDetailsService {

    private UserRepository userRepository;

    @Autowired
    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Here I am retrieving the user from my database where the primary key is 
// email
        User user = userRepository.findByEmail(username);

        if(user == null) {
            throw new UsernameNotFoundException("Username not found!");
        }

        CustomUserDetails customUserDetails = new CustomUserDetails(user);
        return customUserDetails;
    }
}
Angel Gruevski
  • 127
  • 1
  • 5
  • Sorry for not being very explicit in my question. I have edited it. I hope you can understand it better now. Thanks – André Abreu Jan 16 '18 at 10:27