In today's digital age, online security is a top concern for both website owners and users. To combat this, many websites are adopting passwordless login systems to eliminate the need for users to remember and enter passwords. Laravel, a popular PHP web application framework, has made it easy to implement passwordless login with the help of the grosv/laravel-passwordless-login composer package.
In this tutorial, we will take you through the steps required to set up a passwordless login system with Laravel using a magic link. This system will allow users to simply enter their email or username, receive an email with a magic link, and use it to log in to the website.
Step 1: Install Laravel
This is optional; however, if you have not created the laravel app, then you may go ahead and execute the below command:
composer create-project laravel/laravel example-app
Step 2: Setup Database Configuration
After successfully installing the laravel app then configuring the database setup. We will open the ".env" file and change the database name, username and password in the env file.
.env
Step 3: Install Auth Scaffold
Laravel's laravel/ui package provides a quick way to scaffold all of the routes and views you need for authentication using a few simple commands:
Next, we need to generate auth scaffold with bootstrap, so let's run the below command:
Now go to resources\views\layouts\app.blade.php
remove the bellow line.
and replaced this with the below line.
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
crossorigin="anonymous">
crossorigin="anonymous"></script>
Step 4: Install grosv/laravel-passwordless-login Package
In this step, we will install grosv/laravel-passwordless-login to generate the login url. so let's run the below command:
composer require grosv/laravel-passwordless-login
Step 5: Update Login Blade File
In this step, we will update auth login blade file. in this file we will add a new Password Less Login link. so let's update the following file:
resources/views/auth/login.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('login') }}">
@csrf
<div class="row mb-3">
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<div class="col-md-6 offset-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember">
{{ __('Remember Me') }}
</label>
</div>
</div>
</div>
<div class="row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
OR
<button type="submit" class="btn btn-success" name="submit" value="password-less">
Password Less Login
</button>
<br/>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Step 6: Update LoginController
<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Notifications\SendPasswordLessLinkNotification;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function login(Request $request)
{
if($request->input('submit') == 'password-less'){
$user = $this->loginViaPasswordLessLink($request);
if(!$user){
return redirect()->route('login')
->withErrors(['email' => 'User with this email does not exist.'])
->withInput();
}
return redirect()->route('login')
->withMessage('Password Less Link Sent to the registered email ID.');
}
$this->validateLogin($request);
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
if ($request->hasSession()) {
$request->session()->put('auth.password_confirmed_at', time());
}
return $this->sendLoginResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Write code on Method
*
* @return response()
*/
public function loginViaPasswordLessLink(Request $request)
{
$user = User::where('email', $request->input('email'))->first();
if ($user) {
$user->notify(new SendPasswordLessLinkNotification());
}
return $user;
}
}
Step 7: Create Notification Class
we will update the SendPasswordLessLinkNotification.php notification for sending emails with a magic link. let's create a notification by following the command:
php artisan make:notification SendPasswordLessLinkNotification
Next update your code using this step
app/Notifications/SendPasswordLessLinkNotification.php
Run Laravel App Now:
php artisan serve
Now, Go to your web browser, type the given URL