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!