Laravel Auth: Login With Email Or Username (In One Field)

Quick tip for you guys. What if in your project users can login not only with email but also with some other field, like “username” or “user_id” or whatever? By default Laravel allows only one field like ’email’. That’s actually easy to change.

Let’s imagine that you already have a field username in your users table and need to check the login form result. So there are only two input fields – login and password. And login may be either email or username. How can we check both?

You need to add some code into a file app/Http/Auth/LoginController.php and override login() method:

public function login(Request $request)
{
    $this->validate($request, [
        'login'    => 'required',
        'password' => 'required',
    ]);

    $login_type = filter_var($request->input('login'), FILTER_VALIDATE_EMAIL ) 
        ? 'email' 
        : 'username';

    $request->merge([
        $login_type => $request->input('login')
    ]);

    if (Auth::attempt($request->only($login_type, 'password'))) {
        return redirect()->intended($this->redirectPath());
    }

    return redirect()->back()
        ->withInput()
        ->withErrors([
            'login' => 'These credentials do not match our records.',
        ]);
    } 

}

Let’s look a little deeper:

$login_type = filter_var($request->input('login'), FILTER_VALIDATE_EMAIL ) 
  ? 'email' 
  : 'username';

This line of code is checking whether user inputted an email or some other string – which then is interpreted as username.

$request->merge([
    $login_type => $request->input(‘login')
]);

This one is adding a variable into $request array – by default we have ‘login’ variable, but what we actually need is ’email’ or ‘username’ – so it’s inserted here.

if (Auth::attempt($request->only($login_type, 'password'))) {
    return redirect()->intended($this->redirectPath());
}

And finally we’re checking the credentials, but only the particular one we need – it comes from $login_type variable.

Simple, isn’t it?

Like our articles?
Check out our Laravel online courses!

7 COMMENTS

  1. all u need to change is

    public function username()
    {
    return filter_var($request->input(‘login’), FILTER_VALIDATE_EMAIL )
    ? ’email’
    : ‘username’;
    }

    • Where is the $request variable? The username() function does not take parameters so you need to tweak your code abig to something like this

      protected function credentials(Request $request)
      {
      $type = filter_var($request->input(‘identity’), FILTER_VALIDATE_EMAIL)
      ? ’email’
      : ‘phone_number’;

      $request->merge([
      $type => $request->input(‘identity’)
      ]);

      return $request->only($type, ‘password’);
      }

      public function username()
      {
      return ‘identity’;
      }

  2. By this implementation is important to note that username should not allowed dots and @ in input, otherwise FILTER_VALIDATE_EMAIL returns true on username

  3. Is it ok to use:
    return $this->sendFailedLoginResponse($request);

    instead of:
    return redirect()->back()
    ->withInput()
    ->withErrors([
    ‘login’ => ‘These credentials do not match our records.’,
    ]);
    }

LEAVE A REPLY

Please enter your comment!
Please enter your name here