When building my application, I used the Laravel authentication scaffolding by running php artisan make:auth
which was great and saved me a lot of time.
However, I am running into an issue with users not being able to login because they can't remember what case they used for their email when they originally signed up.
For example, a user that signed up with [email protected]
can not login with [email protected]
.
I understand from my research that technically the part prior to the @ is case sensitive by virtue of the spec, and that the two emails above could, in theory, belong to two different people. In my situation though, I don't foresee that being enough of a likelihood that I would need to enforce this on login.
I'm using a Postgres database so I'm looking to just replace the email database lookup in Auth::attempt()
with ilike
instead of like
if possible. However, I can't for the life of me find where this is in the source and therefore have no idea how I would go about overwriting this.
Tl;dr how do I override Laravel's default authentication to do email lookup in a case insensitive manner?
I ended up solving the issue by first taking @btl advice and implementing a mutator method on the email attribute. I didn't want to have to go through and change all the emails for existing users, and felt like in case I ever did run into an issue in which I'd like to have case-sensitivity back, I wanted a solution that could be undone easily.
app/User.php
public function getEmailAttribute($value) {
return strtolower($value);
}
app/Http/Controllers/Auth/LoginController.php
protected function credentials()
{
$username = $this->username();
$credentials = request()->only($username, 'password');
if (isset($credentials[$username])) {
$credentials[$username] = strtolower($credentials[$username]);
}
return $credentials;
}
Unfortunately I couldn't figure out how to apply this same logic to the ForgotPasswordController.php
but for now I'll live. Logging in seems to work regardless of email case now.
Add an mutator method on your user model to make the email all lowercase:
public function setEmailAttribute($value)
{
$this->attributes['email'] = strtolower($value);
}
Whenever a user registers, the email will always be converted to lower case.
Or, use an accessor on the user model:
public function getEmailAttribute($value)
{
return strtolower($value);
}
That way the original value is preserved in the database, but whenever you call $user->email it will be lowercase. You'd just need to convert your user's input when logging to to lowercase when making the strict comparison.