In this article, we will see how to login with magic link in laravel 9. Here, we will learn passwordless login with magic link laravel 7, laravel 8 and laravel 9. It can be auto login through the link laravel 9.
In laravel 9, if you want to passwordless login and register then you can use magic link concept. In this user don't need to remember password. User can login using magic link by entering user name or email and getting email with link. if you click on the link it can directly login to system.
So, le's see laravel 8/9 magic link login, laravel 8/9 password less login, laravel 9 login and registration, how to login with the link in laravel 8 and laravel 9.
We will use grosv/laravel-passwordless-login package. It's a simple, safe magic login link generator for laravel.
Step 1: Install Laravel 9 Application
Step 2: Configure Database
Step 3: Install Auth Scaffold
Step 4: Install grosv/laravel-passwordless-login package
Step 5: Update Login File
Step 6: Update LoginController
Step 7: Create Notification Class
Step 8: Run Laravel 9 Application
In this step, we will install the laravel 9 application using the following command.
composer create-project laravel/laravel laravel9_magic_link_example
Now, we will configure database details like user name, database name, etc.
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel9_magic_link
DB_USERNAME=root
DB_PASSWORD=root
Now, we will install the laravel auth scaffold using the laravel/ui package. So, run the following command.
composer require laravel/ui
After that, we will basic log in and register using the bootstrap auth scaffold
php artisan ui bootstrap --auth
Then, install npm packages using the following command.
npm install
Now, build CSS using the following command.
npm run build
In this step, we will Install grosv/laravel-passwordless-login package using the following composer command.
composer require grosv/laravel-passwordless-login
Now, we will update the login.blade.php file. In this file, we will add a magic link. So, add the following code to that 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
@if (session('message'))
<div class="alert alert-success">{{ session('message') }}</div>
@endif
<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" 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="magic-link">
Send Magic Link
</button>
<br/>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Now, we will update LoginController.php. So, add the following code to that file.
app/Http/Controllers/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use App\Models\User;
use App\Notifications\SendMagicLinkNotification;
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');
}
/**
* Write code on Method
*
* @return response()
*/
public function login(Request $request)
{
if($request->input('submit') == 'magic-link'){
$user = $this->loginViaMagicLink($request);
if(!$user){
return redirect()->route('login')
->withErrors(['email' => 'User with this email does not exist.'])
->withInput();
}
return redirect()->route('login')
->withMessage('Magic Link Sent to the Registered Email Address');
}
$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 loginViaMagicLink(Request $request)
{
$user = User::where('email', $request->input('email'))->first();
if ($user) {
$user->notify(new SendMagicLinkNotification());
}
return $user;
}
}
In this step, we will create a SendMagicLinkNotification.php notification for sending emails with a magic link.
php artisan make:notification SendMagicLinkNotification
app/Notifications/SendMagicLinkNotification.php
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Grosv\LaravelPasswordlessLogin\LoginUrl;
class SendMagicLinkNotification extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$generator = new LoginUrl($notifiable);
$generator->setRedirectUrl('/home');
$url = $generator->generate();
return (new MailMessage)
->subject('Your Password Less Link!')
->line('Click this link to log in!')
->action('Login', $url)
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
];
}
}
Now, we will run login with the magic link in laravel 9 using the following command.
php artisan serve
You might also like:
- Read Also: Laravel 9 Authentication Using Inertia JS
- Read Also: Laravel 9 Two Factor Authentication With SMS
- Read Also: Laravel 9 Multiple Authentication Using Middleware
- Read Also: Login with Mobile Number using Laravel Custom Auth