In this tutorial, we’ll walk through creating a secure login system in Laravel that combines:
– Traditional login & registration
– Login via a unique magic link (a secure token)
– Two-Factor Authentication (2FA) for added security
– A dashboard showing user-specific content (e.g. reviews)
This is a great way to create a secure and user-friendly authentication flow for apps that need quick logins via email or external links while maintaining strong security.
Tools & Packages Used
– Laravel Breeze (auth scaffolding)
– Laravel Fortify (2FA)
– Laravel’s built-in Auth system
Step 1: Set Up Laravel & Breeze
Create a new Laravel project and install Breeze:
composer create-project laravel/laravel login-app
cd login-app
composer require laravel/breeze –dev
php artisan breeze:install
npm install && npm run dev
php artisan migrate
Step 2: Add Login Token Field
Generate a migration:
php artisan make:migration add_login_token_to_users_table
Edit the migration:
Schema::table(‘users’, function (Blueprint $table) {
$table->string(‘login_token’)->nullable()->unique();
});
Then run:
php artisan migrate
Step 3: Magic Link Login Route
In routes/web.php:
Route::get(‘/magic-login/{token}’, function ($token) {
$user = \App\Models\User::where(‘login_token’, $token)->firstOrFail();
\Illuminate\Support\Facades\Auth::login($user);
return redirect()->route(‘2fa.prompt’);
});
Step 4: Install Laravel Fortify for 2FA
Install Fortify:
composer require laravel/fortify
php artisan vendor:publish –provider=”Laravel\Fortify\FortifyServiceProvider”
php artisan migrate
In config/fortify.php:
‘features’ => [
Features::twoFactorAuthentication([
‘confirmPassword’ => false,
]),
]
Register in config/app.php:
App\Providers\FortifyServiceProvider::class,
Step 5: Add Dashboard and Review Model
Create a model and migration:
php artisan make:model Review -m
Update the migration:
Schema::create(‘reviews’, function (Blueprint $table) {
$table->id();
$table->foreignId(‘user_id’)->constrained()->onDelete(‘cascade’);
$table->string(‘content’);
$table->timestamps();
});
Then migrate:
php artisan migrate
Step 6: Create Dashboard Controller and View
Create controller:
php artisan make:controller DashboardController
In controller:
public function index() {
$reviews = \App\Models\Review::where(‘user_id’, auth()->id())->get();
return view(‘dashboard’, compact(‘reviews’));
}
In routes/web.php:
Route::middleware([‘auth’])->group(function () {
Route::get(‘/dashboard’, [DashboardController::class, ‘index’])->name(‘dashboard’);
});
Create Blade view in resources/views/dashboard.blade.php:
<h1>Welcome {{ auth()->user()->name }}</h1>
<h2>Your Reviews:</h2>
<ul>
@foreach($reviews as $review)
<li>{{ $review->content }}</li>
@endforeach
</ul>
Security Tips
– Token should be unique and long (64+ characters)
– You can add an expiration (e.g., login_token_expires_at)
– Optionally regenerate token after every login
– Log login attempts for auditing
Final Thoughts
Combining magic login links with two-factor authentication gives users a smooth experience while keeping your app secure. Laravel’s ecosystem makes this simple to implement using built-in packages like Breeze and Fortify.
This setup is ideal for:
– Client dashboards
– Internal tools
– Invitation-based platforms