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:
- An application written in Laravel
- Installed Composer
- 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!