DEV Community

Cover image for Laravel Password less Login using Magic Link.
shani singh
shani singh

Posted on

Laravel Password less Login using Magic Link.

In this post, I am going to explain about login with Magic Link in LARAVEL 9.

After Installing Laravel and Laravel Authentication open code project in code editor & follow the steps below.

Step -1

To make password less login with Magic Link, we are going to us Laravel Password Less Package.

All you need to do is run the composer command.

composer require grosv/laravel-passwordless-login
Enter fullscreen mode Exit fullscreen mode

Step - 2

Make Changes in login view file, open resources/views/auth/login.blade.php and update the code below.

@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-info">{{ session('message') }}</div>
                        @endif

                        <div class="row mb-3">
                            <label for="username" class="col-md-4 col-form-label text-md-end">{{ __('Username') }}</label>

                            <div class="col-md-6">
                                <input id="username" type="text" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autocomplete="username" autofocus>

                                @error('username')
                                    <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" name="submit" class="btn btn-primary" value="login">
                                    {{ __('Login') }}
                                </button>

                                or

                                <button type="submit" class="btn btn-secondary" name="submit" value="magic-link">
                                    {{ __('Send Magic Link') }}
                                </button>
                            </div>
                        </div>

                        <div class="row mb-0 mt-3">
                            <div class="col-md-8 offset-md-4">
                                @if (Route::has('password.request'))
                                    <a class="btn btn-link" href="{{ route('password.request') }}">
                                        {{ __('Forgot Your Password?') }}
                                    </a>
                                @endif

                                <a class="btn btn-link" href="{{ route('otp.login') }}">
                                    {{ __('Login With OTP.') }}
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
Enter fullscreen mode Exit fullscreen mode

Step - 3

Update the app/Http/Controllers/Auth/LoginControlller.php add the login & Login with Magic Link Function.

<?php

namespace App\Http\Controllers\Auth;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Notifications\SendMagicLinkNotification;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

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 username()
    {
        return 'username';
    }

    public function login(Request $request)
    {


        if($request->input('submit') == 'magic-link'){
            $user = $this->loginViaMagicLink($request);

            if(!$user){
                return redirect()->route('login')
                ->withErrors(['username' => 'User with this username does not exist.'])
                ->withInput();
            }

            return redirect()->route('login')
            ->withMessage('Magic Link Sent to the registered email ID.');
        }

        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        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);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

    public function loginViaMagicLink(Request $request)
    {
        $user = User::where('username', $request->input('username'))->first();

        if ($user) {
            $user->notify(new SendMagicLinkNotification());
        }

        return $user;
    }
}
Enter fullscreen mode Exit fullscreen mode

Step - 4

Create notification to send magic link on registered email.

php artisan make:notification SendMagicLinkNotification
Enter fullscreen mode Exit fullscreen mode

After creating the notification open it from app/Notifications and update the code below.

<?php

namespace App\Notifications;

use Grosv\LaravelPasswordlessLogin\LoginUrl;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

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 Login Magic 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 [
            //
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

That's it now you visit on login page and you will see the magic link button on login page.

Login

After you hit send magic link you are going to get email like.

Email

I hope this will help login with MAGIC LINK in LARAVEL 9.

Complete Video Tutorial on YouTube.

If you face any issues while implementing, please comment your query.

Thank You for Reading

Reach Out To me.
Twitter
Instagram
YouTube

Top comments (0)