[5.x]: E-Mail can take precedence over username in login form
What happened?
Description
I'm seeing an issue where a user can't log in with their username, if there's another user that has a different username, but the same e-mail. Even if that other user is disabled.
Steps to reproduce
- Set
useEmailAsUsernametofalseinconfig/general.php. - Create a user with username
[email protected]and E-Mail[email protected]. Activate the user. - Create another user with username
boband username[email protected]. Leave it deactivated. - Try to log in with
[email protected]. It may work or it may not, because the database may return either user (there's nothing in the query to order the users, so it's up to the database).
This may seem like a contrived example, but we're seeing this in the real world. In this case, the e-mail is a shared mailbox and the users are synced from an external system.
Expected behavior
I suggest two changes (ideally, I would like to see both implemented):
- If
useEmailAsUsernameis set tofalse, theusernameshould always take precedence over theemailfield. That is, if a user tries to log in, the system should check if there's a match in theusernamefield before checking matches in theemailfield. - If two or more accounts have the same email, but one is disabled, the login should always favor the account that is enabled.
Actual behavior
The query in User::getUserByUsernameOrEmail() just tries to find any user where the username or email match the input, so the login may or may not work.
Craft CMS version
5.8.18
PHP version
No response
Operating system and version
No response
Database type and version
No response
Image driver and version
No response
Installed plugins and versions
Hi, thanks for reporting! We discussed this internally and decided to adjust the Users::getUserByUsernameOrEmail() method to prioritise the credentialed users. The username and email have to be unique among all credentialled users and only credentialed users can log in (with password or passkey), so this change should improve the authentication flow.
@i-just Looks good, thanks!
We’re experiencing the same issue and want to make sure we’re handling it correctly on our end.
We have useEmailAsUsername = true, so email is the primary identifier for login. Both staff and users assume an email maps to a single account.
Pain points:
- Staff search by email and assume the first result is the correct user, without awareness of credentialed vs non-credentialed distinctions.
- Our newer staff members are not always checking whether a user already exists before creating a new account, which can unintentionally introduce duplicate emails.
- Duplicate emails make it easy to act on the wrong account, even if the other user is disabled.
- On the front end, we’re concerned about users registering with an email that already exists, only to hit issues later during activation or login.
Is there a supported way to enforce email uniqueness without a custom module? If so, what are the pitfalls or edge cases we should be aware of?
Staff search by email and assume the first result is the correct user, without awareness of credentialed vs non-credentialed distinctions.
@mjniland1 I just fixed that for the next release, so going forward, active, non-pending users will always be shown first. (856bc2d514d8ba9262d01949e56dcd318bbc8034)