How to Create OTP Authentication in Laravel Like Authenticator Apps

If you want to build OTP (One-Time Password) authentication in Laravel similar to apps like:

  • Google Authenticator
  • Microsoft Authenticator
  • Authy

Then you need to implement TOTP (Time-based One-Time Password) authentication.

This is much more secure than normal SMS OTPs because:

  • Codes change every 30 seconds
  • Works offline
  • Uses secret keys
  • Follows RFC 6238 standard
  • Used in production by most modern apps

Types of OTP in Laravel

TypeExampleRecommended
SMS OTPMobile login
Email OTPLogin/Register
TOTP Authenticator AppGoogle Authenticator✅✅✅
WhatsApp OTPBusiness apps
Hardware Token OTPEnterprise securityAdvanced

Best Package for Laravel

Use:

PragmaRX Google2FA Package

This package helps generate:

  • Secret Keys
  • QR Codes
  • OTP Verification
  • TOTP codes

Install Package

composer require pragmarx/google2fa

For QR Code generation:

composer require bacon/bacon-qr-code

Database Migration

Add OTP secret column to users table.

php artisan make:migration add_2fa_columns_to_users_table

Migration:

Schema::table('users', function (Blueprint $table) {
$table->text('google2fa_secret')->nullable();
$table->boolean('google2fa_enabled')->default(false);
});

Run:

php artisan migrate

Generate Secret Key

Controller:

<?php

namespace App\Http\Controllers;

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

class TwoFactorController extends Controller
{
public function enable2FA()
{
$google2fa = new Google2FA();

$secret = $google2fa->generateSecretKey();

$user = Auth::user();

$user->google2fa_secret = $secret;
$user->save();

$QR_Image = $google2fa->getQRCodeInline(
'MyLaravelApp',
$user->email,
$secret
);

return view('2fa.enable', [
'QR_Image' => $QR_Image,
'secret' => $secret
]);
}
}

Blade View

<h2>Scan QR Code</h2>

<div>
{!! $QR_Image !!}
</div>

<p>Secret Key: {{ $secret }}</p>

How It Works

User:

  1. Opens Google Authenticator
  2. Scans QR code
  3. App stores secret key
  4. Generates 6-digit OTP every 30 seconds

Verify OTP

Controller Method:

public function verify2FA(Request $request)
{
$request->validate([
'otp' => 'required'
]);

$google2fa = new Google2FA();

$user = Auth::user();

$valid = $google2fa->verifyKey(
$user->google2fa_secret,
$request->otp
);

if ($valid) {

$user->google2fa_enabled = true;
$user->save();

return response()->json([
'success' => true,
'message' => 'OTP Verified'
]);
}

return response()->json([
'success' => false,
'message' => 'Invalid OTP'
], 422);
}

Verification Form

<form method="POST" action="/verify-2fa">
@csrf

<input type="text" name="otp" placeholder="Enter OTP">

<button type="submit">
Verify
</button>
</form>

Login Flow

Typical production flow:

User Login

Email + Password Verified

Check if 2FA enabled

Ask OTP

Verify OTP

Login Success

Production Security Tips

Encrypt Secret Keys

Very important.

Use Laravel encryption:

$user->google2fa_secret = encrypt($secret);

Read:

$secret = decrypt($user->google2fa_secret);

Add Rate Limiting

Prevent brute-force attacks.

Route::post('/verify-2fa')
->middleware('throttle:5,1');

Recovery Codes

Generate backup recovery codes.

Example:

Str::random(10);

Store hashed recovery codes.

Session-based Verification

After successful OTP:

session([
'2fa_verified' => true
]);

API Authentication Example

For Laravel APIs:

POST /api/login

Response:

{
"requires_2fa": true,
"temp_token": "xxxx"
}

Then:

POST /api/verify-otp

After verification:

{
"access_token": "jwt-token"
}

Recommended Laravel Stack

FeatureRecommended
AuthLaravel Sanctum
OTPGoogle2FA
QR CodeBaconQrCode
QueueRedis
SMS OTPTwilio
WhatsApp OTPWATI
Email OTPLaravel Notifications

Difference Between SMS OTP & Authenticator OTP

FeatureSMS OTPAuthenticator OTP
Internet RequiredYesNo
SIM Swap RiskHighLow
More Secure
CostSMS chargesFree
Enterprise GradeMediumHigh

Advanced Features

You can also implement:

  • Device remembering
  • Trusted devices
  • OTP expiry handling
  • Multi-device authentication
  • Backup recovery codes
  • WebAuthn / Passkeys
  • Biometric login

Full Laravel Routes

Route::middleware('auth')->group(function () {

Route::get('/enable-2fa', [TwoFactorController::class, 'enable2FA']);

Route::post('/verify-2fa', [TwoFactorController::class, 'verify2FA']);
});

Recommended Folder Structure

app/
├── Http/
│ ├── Controllers/
│ │ └── TwoFactorController.php

├── Services/
│ └── OTPService.php

├── Actions/
│ └── VerifyOTPAction.php

Real-World Apps Using TOTP

  • Google Authenticator
  • Microsoft Authenticator
  • LastPass Authenticator
  • Duo Mobile
  • Authy

Final Recommendation

For modern Laravel applications:

✅ Use Password + TOTP
✅ Store encrypted secrets
✅ Add recovery codes
✅ Use throttling
✅ Use Sanctum/JWT for APIs
✅ Use queues for SMS/email OTPs

Avoid relying only on SMS OTP for sensitive applications.