Two-Factor Authentication (2FA) using Laravel

by Sunil M. 4 minute read 8 views

Laravel Two-Factor Authentication improves login safety, reduces data breach risks, and builds user trust by adding an extra security layer beyond passwords.

Key Points

  • 81% of data breaches happen due to weak or stolen passwords without two-factor authentication.
  • Adding 2FA reduces unauthorized account access risks by up to 99% in Laravel applications.
  • Over 85% of companies integrate 2FA to meet compliance and strengthen overall application security.

Introduction

In today’s digital world, protecting user data is more crucial than ever. Relying only on username and password authentication no longer offers sufficient defense against modern threats. That’s when Two-Factor Authentication (2FA) becomes essential.

Adding an extra layer of security, 2FA greatly reduces the risk of unauthorized access. If you’re working with Laravel, incorporating 2FA is simple thanks to its built-in authentication scaffolding and robust third-party packages. Whether you’re developing SaaS platforms, eCommerce sites, or custom web development projects, implementing 2FA provides your users with enhanced security and peace of mind.

What is Two-Factor Authentication (2FA)?

Two-Factor Authentication requires users to verify their identity using two separate methods:

  1. Something they know (password)
  2. Something they have (a one-time code sent via SMS, email, or authenticator app)

This extra step ensures that even if passwords are compromised, attackers cannot access the account without the second factor.

Methods to Implement 2FA in Laravel

We’ll cover two approaches to add 2FA in Laravel:

  1. Using Laravel Jetstream (Quick Setup)
  2. Custom 2FA with Google Authenticator (Hands-on Implementation)

Method 1: Using Laravel Jetstream (Easiest Way)

Laravel Jetstream comes with built-in support for Two-Factor Authentication.

Step 1: Install Jetstream

                                        composer require laravel/jetstream
php artisan jetstream:install livewire
npm install && npm run dev
php artisan migrate
                                    

This installs authentication scaffolding with user management features.

Step 2: Enable 2FA in User Profile

After installation:

  1. Register or log in.
  2. Navigate to Profile → Two-Factor Authentication.
  3. Enable 2FA by scanning the generated QR code with Google Authenticator or Authy.

Laravel automatically generates:

  • QR codes
  • Recovery codes
  • TOTP (Time-based One-Time Passwords)

Step 3: Test the Login Flow

  1. Log out of the application.
  2. Log back in using your email and password.
  3. Laravel prompts for a 2FA code from the authenticator app.
  4. Enter the OTP → access granted.

And that’s it! Jetstream makes 2FA integration very easy.

Method 2: Custom 2FA with Google Authenticator

If you want more flexibility, you can build a custom 2FA system using the PragmaRX Google2FA package. This is ideal for businesses that prefer custom web development and complete control over user security.

Step 1: Install the Package

                                        composer require pragmarx/google2fa-laravel
                                    

Step 2: Publish Configuration

                                        php artisan vendor:publish --provider="PragmaRX\Google2FALaravel\ServiceProvider"
                                    

This creates the config/google2fa.php file.

Step 3: Update Users Table

Add a new column for storing secret keys:

                                        // database/migrations/xxxx_xx_xx_add_google2fa_to_users.php

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('google2fa_secret')->nullable();
    });
}
                                    

Run migration:

                                        php artisan migrate
                                    

Step 4: Generate Secret for User

In your ProfileController:

                                        use PragmaRX\Google2FA\Google2FA;
use Illuminate\Support\Facades\Auth;

public function enable2fa()
{
    $google2fa = new Google2FA();

    // Generate a new secret key
    $secret = $google2fa->generateSecretKey();

    // Save the secret for the logged-in user
    $user = Auth::user();
    $user->google2fa_secret = $secret;
    $user->save();

    // Generate QR code URL
    $QR_Image = \Google2FA::getQRCodeUrl(
        'MyApp',
        $user->email,
        $secret
    );

    return view('2fa.enable', compact('QR_Image', 'secret'));
}
                                    

Step 5: Display QR Code

Install QR Code package:

                                        composer require bacon/bacon-qr-code
                                    

In resources/views/2fa/enable.blade.php:

                                        <h3>Scan this QR Code in Google Authenticator</h3>
<img src="{{ \SimpleSoftwareIO\QrCode\Facades\QrCode::size(200)->generate($QR_Image) }}" />
<p>Secret: {{ $secret }}</p>
                                    

Step 6: Verify OTP on Login

Modify LoginController:

                                        use PragmaRX\Google2FA\Google2FA;

protected function authenticated(Request $request, $user)
{
    if ($user->google2fa_secret) {
        session(['2fa:user:id' => $user->id]);
        Auth::logout();

        return redirect('/2fa/verify');
    }

    return redirect()->intended($this->redirectPath());
}
                                    

Step 7: Create 2FA Routes and Controller

web.php

                                        Route::get('/2fa/verify', [TwoFactorController::class, 'index'])->name('2fa.index');
Route::post('/2fa/verify', [TwoFactorController::class, 'verify'])->name('2fa.verify');
                                    

TwoFactorController.php

                                        use PragmaRX\Google2FA\Google2FA;
use Illuminate\Support\Facades\Auth;
use App\Models\User;

class TwoFactorController extends Controller
{
    public function index()
    {
        return view('2fa.verify');
    }

    public function verify(Request $request)
    {
        $request->validate([
            'otp' => 'required|digits:6'
        ]);

        $google2fa = new Google2FA();
        $user = User::find(session('2fa:user:id'));

        if ($google2fa->verifyKey($user->google2fa_secret, $request->otp)) {
            Auth::login($user);
            session()->forget('2fa:user:id');
            return redirect()->intended('/');
        }

        return back()->withErrors(['otp' => 'Invalid OTP. Try again!']);
    }
}
                                    

Step 8: Create OTP Verification View

                                        resources/views/2fa/verify.blade.php
<form method="POST" action="{{ route('2fa.verify') }}">
    @csrf
    <label>Enter 2FA Code:</label>
    <input type="text" name="otp" required>
    <button type="submit">Verify</button>
</form>
                                    

Final Flow of Custom 2FA

  1. User logs in with email & password.
  2. If 2FA is enabled → redirected to OTP verification page.
  3. User enters the OTP from Google Authenticator.
  4. Access is granted only if the OTP is valid.

Best Practices for 2FA in Laravel

  • Always provide backup codes for users.
  • Encourage using authenticator apps (safer than SMS).
  • Log all 2FA activities for auditing and monitoring.
  • Offer recovery options (e.g., email verification or admin request).
  • For complex projects, it’s a smart move to hire Laravel developers with strong Laravel security expertise.

Final Words

Adding Two-Factor Authentication in Laravel is an excellent way to strengthen your application’s security and build user trust. With Laravel Jetstream or third-party packages, integrating 2FA is straightforward and highly effective.

Whether you’re working on a startup, an enterprise-level project, or a custom web development solution, securing user accounts should always be your top priority. If your team lacks in-house expertise, it’s wise to hire Laravel developers who can integrate 2FA and other advanced security features seamlessly.

Tech Stack & Version

Frontend

  • Blade
  • Tailwind CSS

Backend

  • Laravel 10
  • MySQL

Deployment

  • AWS
  • DigitalOcean
img

©2025Digittrix Infotech Private Limited , All rights reserved.