In modern applications, user experience and security go hand in hand. Many developers are now moving toward passwordless login systems that allow users to authenticate securely without remembering complex passwords.
One of the easiest ways to achieve this in Laravel is by using a Magic Link – a unique, one-time URL sent to the user’s email. Once clicked, the user is automatically logged in without needing to enter a password.
In this tutorial, we’ll build a passwordless login system in Laravel using the Maize Laravel Magic Login package.
First, create a fresh Laravel project (you can skip this if you already have one):
composer create-project laravel/laravel laravel-magic-login-tutorial
cd laravel-magic-login-tutorial
Since we need authentication scaffolding, install Laravel UI:
composer require laravel/ui
php artisan ui bootstrap --auth
npm install && npm run dev
This gives you login, registration, and basic auth setup.
Next, install the Maize Laravel Magic Login package:
composer require maize-tech/laravel-magic-login
You can publish the config and migration files and run the migrations with:
php artisan magic-login:install
Now, create a controller to handle magic link requests.
File: app/Http/Controllers/MagicLinkController.php
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Maize\MagicLogin\Facades\MagicLink;
class MagicLinkController extends Controller
{
public function loginPage()
{
return view('login');
}
public function sendMagicLink(Request $request)
{
$request->validate(['email' => 'required|email']);
$user = User::where('email', $request->email)->first();
if (! $user) {
return back()->withErrors([
'email' => 'This email address is not registered in our system.',
]);
}
// Generate and send magic link (expires in 60 minutes)
MagicLink::make(
authenticatable: $user,
expiration: 60,
notify: true
);
return back()->with('success', 'We’ve sent you a magic login link. Check your email!');
}
}
Open routes/web.php
and add:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\MagicLinkController;
use Maize\MagicLogin\Facades\MagicLink;
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
// Passwordless Login Routes
Route::get('/password-less-login', [MagicLinkController::class, 'loginPage'])->name('magic.login');
Route::post('/magic-link', [MagicLinkController::class, 'sendMagicLink'])->name('magic.send');
// Register package routes
MagicLink::route();
Inside config/magic-login.php
, set the redirect URL:
'redirect_url' => '/home',
'logins_limit' => 1,
So after clicking the magic link, users are redirected to /home
.
In .env
, add Mailtrap SMTP credentials:
MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_mailtrap_username
MAIL_PASSWORD=your_mailtrap_password
MAIL_ENCRYPTION=tls
[email protected]
MAIL_FROM_NAME="Laravel Magic Login"
Open resources/views/auth/login.blade.php
and add a link for passwordless login:
<hr>
<a href="{{ route('magic.login') }}" class="btn btn-primary">
Send Magic Link
</a>
This will appear below the normal login form.
Create resources/views/login.blade.php
for users to enter their email and receive a magic link.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Passwordless Login</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background-color: #f5f5f5;
}
.login-card {
max-width: 400px;
padding: 2rem;
margin: 5% auto;
background: #fff;
border-radius: 0.5rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<div class="login-card text-center">
@if ($errors->any())
<div class="alert alert-danger alert-dismissible fade show" role="alert">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
@if (session('success'))
<div class="alert alert-success alert-dismissable">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
<strong>{{ session('success') }}</strong>
</div>
@endif
<h4 class="mb-3">Login with Magic Link</h4>
<p class="text-muted mb-4">Enter your email to receive a login link</p>
<form method="post" action="{{ route('magic.send') }}">
@csrf
<div class="mb-3 text-start">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" name="email" placeholder="[email protected]" required>
</div>
<button type="submit" class="btn btn-primary w-100">Send Magic Link</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
✅ The user can now choose between:
Logging in with email & password (default Laravel login).
Logging in with passwordless Magic Link via email.
Once the user clicks the email link, they’re redirected and logged into your Laravel app securely.
We successfully implemented passwordless authentication in Laravel using Magic Links. This method makes login easier and more secure for your users.
For more advanced features and customization, check out the package documentation:
👉 Laravel Magic Login GitHub Repository