Enhancing Security: Integrating Two-Factor Authentication (2FA) in Your Laravel Application

Share this post on:

Why 2FA?

Dual-Factor By requiring a second factor in addition to a password—typically an email or text message—authentication greatly improves security. Even if they have acquired the password, this extra step makes it considerably more difficult for unauthorized individuals to get access.

Required conditions

Make sure you have the following before we begin:

  1. An application written in Laravel
  2. Installed Composer
  3. A fundamental comprehension of Laravel authentication

1) Install the Required Package

First, we need to install the pragmarx/google2fa-laravel package, which provides a
simple way to integrate Google 2FA into Laravel. composer require pragmarx/google2fa-laravel

After the installation, publish the configuration file:

php artisan vendor:publish —
provider=”PragmaRX\Google2FALaravel\ServiceProvider”

2) Set Up Two-Factor Authentication

Add Middleware

Create middleware to ensure users who have not set up 2FA are prompted to do so.
php artisan make:middleware TwoFactorAuth

In app/Http/Middleware/TwoFactorAuth.php:

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class TwoFactorAuth
{
 public function handle($request, Closure $next)
 {
 $user = Auth::user();
 if ($user->google2fa_secret === null) {
 return redirect()->route('2fa.setup');
 }
 return $next($request);
 }
}

Register Middleware

In app/Http/Kernel.php, register the middleware:
protected $routeMiddleware = [
 // ...
 '2fa' => \App\Http\Middleware\TwoFactorAuth::class,
];

Modify User Model

Update the User model to include 2FA fields

<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use PragmaRX\Google2FALaravel\Support\Auth;
class User extends Authenticatable
{
 use Auth;
 protected $fillable = [
 'name', 'email', 'password', 'google2fa_secret',
 ];
 protected $hidden = [
 'password', 'remember_token', 'google2fa_secret',
 ];
}

Create Migration

Add the google2fa_secret field to the users table

php artisan make:migration add_google2fa_secret_to_users_table —
table=users

In the migration file:

public function up()
{
Schema::table(‘users’, function (Blueprint $table) {
$table->string(‘google2fa_secret’)->nullable();
});
}
public function down()
{
Schema::table(‘users’, function (Blueprint $table) {
$table->dropColumn(‘google2fa_secret’);
});
}
Run the migration:
php artisan migrate

3) Set Up Routes and Controller

Define Routes

In routes/web.php:

use App\Http\Controllers\TwoFactorAuthController;
Route::get('2fa/setup', [TwoFactorAuthController::class, 'showSetupForm'])-
>name('2fa.setup');
Route::post('2fa/setup', [TwoFactorAuthController::class, 'setup'])-
>name('2fa.setup.post');
Route::post('2fa/verify', [TwoFactorAuthController::class, 'verify'])-
>name('2fa.verify');

Create Controller

Generate a controller for handling 2FA setup and verification:

php artisan make:controller TwoFactorAuthController

In app/Http/Controllers/TwoFactorAuthController.php:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PragmaRX\Google2FALaravel\Google2FA;
use Auth;
class TwoFactorAuthController extends Controller
{
 protected $google2fa;
 public function __construct(Google2FA $google2fa)
 {
 $this->google2fa = $google2fa;
 }
 public function showSetupForm(Request $request)
 {
 $user = Auth::user();
 $google2fa_url = "";
if ($user->google2fa_secret === null) {
 $user->google2fa_secret = $this->google2fa-
>generateSecretKey();
 $user->save();
 }
 $google2fa_url = $this->google2fa->getQRCodeInline(
 config('app.name'),
 $user->email,
 $user->google2fa_secret
 );
 return view('2fa.setup', ['google2fa_url' => $google2fa_url,
'secret' => $user->google2fa_secret]);
 }
 public function setup(Request $request)
 {
 $request->validate([
 'verify-code' => 'required|numeric',
 ]);
 $user = Auth::user();
 $valid = $this->google2fa->verifyKey($user->google2fa_secret,
$request->input('verify-code'));
 if ($valid) {
 return redirect()->route('home')->with('success', '2FA setup
successfully.');
 }
 return redirect()->back()->with('error', 'Invalid verification
code, please try again.');
 }
 public function verify(Request $request)
 {
 $request->validate([
 'one_time_password' => 'required|numeric',

]);
 $user = Auth::user();
 $valid = $this->google2fa->verifyKey($user->google2fa_secret,
$request->input('one_time_password'));
 if ($valid) {
 $request->session()->put('2fa_verified', true);
 return redirect()->route('home');
 }
 return redirect()->back()->with('error', 'Invalid verification
code, please try again.');
 }
}

4: Create Views

Create a view for the 2FA setup form at resources/views/2fa/setup.blade.php:

@extends('layouts.app')
@section('content')
<div class="container">
 <h2>Setup Two-Factor Authentication</h2>
 <p>Scan the following QR code with your Google Authenticator app.</p>
 <img src="{{ $google2fa_url }}" alt="2FA QR Code">
 <form method="POST" action="{{ route('2fa.setup.post') }}">
 @csrf
 <div class="form-group">
 <label for="verify-code">Verification Code</label>
 <input type="text" id="verify-code" name="verify-code"
class="form-control" required>
 </div>
 <button type="submit" class="btn btn-primary">Verify and Enable
2FA</button>
 </form>
</div>
@endsection

Conclusion

By integrating Two-Factor Authentication in your Laravel application, you significantly
enhance the security for your users. This extra layer of protection ensures that even if
passwords are compromised, unauthorized access is still prevented. Implementing 2FA might
seem daunting at first, but with Laravel and the pragmarx/google2fa-laravel package, the
process is straightforward and manageable. Stay secure!

Piyush Solanki

PHP Tech Lead & Backend Architect

10+ years experience
UK market specialist
Global brands & SMEs
Full-stack expertise

Core Technologies

PHP 95%
MySQL 90%
WordPress 92%
AWS 88%
  • Backend: PHP, MySQL, CodeIgniter, Laravel
  • CMS: WordPress customization & plugin development
  • APIs: RESTful design, microservices architecture
  • Frontend: React, TypeScript, modern admin panels
  • Cloud: AWS S3, Linux deployments
  • Integrations: Stripe, SMS/OTP gateways
  • Finance: Secure payment systems & compliance
  • Hospitality: Booking & reservation systems
  • Retail: E-commerce platforms & inventory
  • Consulting: Custom business solutions
  • Food Services: Delivery & ordering systems
  • Modernizing legacy systems for scalability
  • Building secure, high-performance products
  • Mobile-first API development
  • Agile collaboration with cross-functional teams
  • Focus on operational efficiency & innovation

Piyush is a seasoned PHP Tech Lead with 10+ years of experience architecting and delivering scalable web and mobile backend solutions for global brands and fast-growing SMEs.

He specializes in PHP, MySQL, CodeIgniter, WordPress, and custom API development, helping businesses modernize legacy systems and launch secure, high-performance digital products.

He collaborates closely with mobile teams building Android & iOS apps, developing RESTful APIs, cloud integrations, and secure payment systems. With extensive experience in the UK market and across multiple sectors, Piyush is passionate about helping SMEs scale technology teams and accelerate innovation through backend excellence.