Authentication by phone number or email

We have a new type of user “CompanyUser” class extends the “User” class. There are two additional fields email and phone number. Now we want to authorise an user by two this fields. How can I customize an user search by username when we do authentication via rest api? As I understood now it works by the username field in the User class.

1 Like

Hi,
Could you please explain your task - do you want to pass either email or phone number in the access token request instead of the username? And then you want to search for users that have the passed value in any of the database columns (EMAIL or PHONE_NUMBER), right?

Yes, I have two three columns USERNAME (standard), EMAIL and PHONE_NUMBER (custom).

You may try changing the DatabaseUserRepository.loadUserByUsername method.
The method will first try to find the user by username, then by email.

The method may look like this:

    @Override
    public User loadUserByUsername(String username) throws UsernameNotFoundException {
        String actualUsername = username;
        List<User> users = dataManager.load(getUserClass())
                .query("where e.username = :username")
                .parameter("username", username)
                .list();

        //try to find the user by email
        if (users.isEmpty()) {
            users = dataManager.load(getUserClass())
                    .query("where e.email = :email")
                    .parameter("email", username)
                    .list();

            if (!users.isEmpty()) {
                //obtain the username in order to create authorities (find assigned roles)
                actualUsername = users.get(0).getUsername();
            }
        }
        if (!users.isEmpty()) {
            User user = users.get(0);
            if (user instanceof AcceptsGrantedAuthorities) {
                ((AcceptsGrantedAuthorities) user).setAuthorities(createAuthorities(actualUsername));
            }
            return user;
        } else {
            throw new UsernameNotFoundException("User not found");
        }
    }

    //just copied the following two methods from AbstractDatabaseUserRepository because they are private there
    private Collection<? extends GrantedAuthority> createAuthorities(String username) {
        return roleAssignmentRepository.getAssignmentsByUsername(username).stream()
                .map(this::createAuthority)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    private GrantedAuthority createAuthority(RoleAssignment roleAssignment) {
        GrantedAuthority authority = null;
        if (RoleAssignmentRoleType.RESOURCE.equals(roleAssignment.getRoleType())) {
            ResourceRole role = resourceRoleRepository.findRoleByCode(roleAssignment.getRoleCode());
            if (role != null) {
                authority = RoleGrantedAuthority.ofResourceRole(role);
            }
        } else if (RoleAssignmentRoleType.ROW_LEVEL.equals(roleAssignment.getRoleType())) {
            RowLevelRole role = rowLevelRoleRepository.findRoleByCode(roleAssignment.getRoleCode());
            if (role != null) {
                authority = RoleGrantedAuthority.ofRowLevelRole(role);
            }
        }
        return authority;
    }
2 Likes