Search code examples
laravelauthenticationlaravel-5laravel-5.5

How to make email login case insensitive with Laravel 5.5 authentication


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?

Solution

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.


Solution

  • 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.