elgibor-solution/laravel-2fa

Two-Factor Authentication package for Laravel supporting Google Authenticator (TOTP) and self-generated codes via SMS/WhatsApp/Email.

1.0.0 2025-08-25 02:14 UTC

This package is not auto-updated.

Last update: 2025-08-26 00:43:03 UTC


README

Two-Factor Authentication package for Laravel that supports:

  • Google Authenticator (TOTP)
  • Self-generated one-time codes with configurable expiry
  • Delivery via Email (built-in), SMS, or WhatsApp (user-provided callbacks)
  • Built-in fraud protection: attempt limits, cooldowns, per-user lock

Requirements

  • PHP 8.1+
  • Laravel 10 or 11

Installation

composer require elgibor-solution/laravel-2fa

Publish config and (optionally) migrations:

php artisan vendor:publish --provider="ESolution\Laravel2FA\Laravel2FAServiceProvider" --tag=2fa-config
php artisan vendor:publish --provider="ESolution\Laravel2FA\Laravel2FAServiceProvider" --tag=2fa-migrations
php artisan migrate

Configuration

config/2fa.php

  • channels.email/sms/whatsapp — enable built-in email sender; provide SMS/WhatsApp callbacks.
  • self_generated_ttl — expiry (seconds) for self-generated codes.
  • code_length — digits for self-generated codes.
  • max_attempts, lock_minutes_after_max — fraud control.
  • cooldown_seconds_between_requests — min time between code requests.
  • totp_drift — allowed time drift for TOTP.
  • issuer — shown in Google Authenticator.
  • tables — override table names if needed.

Binding SMS / WhatsApp senders

In AppServiceProvider@boot() or any service provider:

use Illuminate\Support\Facades\App;

// SMS
App::singleton('2fa.sender.sms', function () {
    return function (string $to, string $message, array $context = []) {
        // Integrate your SMS gateway here
        // Example: Sms::to($to)->send($message);
    };
});

// WhatsApp
App::singleton('2fa.sender.whatsapp', function () {
    return function (string $to, string $message, array $context = []) {
        // Integrate your WhatsApp provider here
        // Example: WhatsApp::sendText($to, $message);
    };
});

Email is supported out of the box via Mail::raw().

Routes

These routes are auto-registered under /2fa with web,auth middleware.

  • POST /2fa/init-totp → Start TOTP setup. Returns { secret, otpauth_uri }.
  • POST /2fa/confirm-totp → Enable TOTP (body: code).
  • POST /2fa/disable → Disable 2FA for the authenticated user.
  • POST /2fa/create → Generate self code and send (body: channel, destination, purpose?).
  • POST /2fa/validate → Validate any code (body: code, purpose?).

Using the Facade

use TwoFA;

// Start TOTP enrollment
$resp = TwoFA::initTotp($user->id); // ['secret' => '...', 'otpauth_uri' => '...']

// Confirm and enable TOTP
$ok = TwoFA::confirmTotp($user->id, $request->code);

// Disable 2FA
TwoFA::disable($user->id);

// Create a self-generated code and deliver it
$res = TwoFA::createSelfGenerated($user->id, 'sms', $user->phone, 'login');

// Validate a code (works for TOTP or self-generated depending on user settings)
$isValid = TwoFA::validate($user->id, $request->code, 'login');

Generating a QR Code for Google Authenticator

initTotp() returns an otpauth:// URI. Render a QR code on your frontend using any QR library (e.g., JavaScript QR libraries). Users can scan that QR with Google Authenticator.

Fraud & Security

  • Hashed codes at rest (HMAC-SHA256 with APP_KEY). Set hash_codes=false to store plaintext (not recommended).
  • Per-code attempt limit (config max_attempts).
  • Cooldown between requests (cooldown_seconds_between_requests).
  • Temporary account lock after too many failures (lock_minutes_after_max). Lock status is tracked in two_fa_settings.locked_until.
  • IP & User-Agent logging for every action in two_fa_logs.

Tip: Add additional monitoring or alerts by listening to model events or querying two_fa_logs.

Middleware

An optional middleware ESolution\Laravel2FA\Http\Middleware\Enforce2FA is included. It blocks requests if the account is currently locked. Register it in app/Http/Kernel.php and apply where needed.

protected $routeMiddleware = [
    // ...
    'enforce2fa' => \ESolution\Laravel2FA\Http\Middleware\Enforce2FA::class,
];

Database

  • two_fa_settings: per-user status, method (totp or self), secret, lock.
  • two_fa_codes: self-generated codes, expiry, attempts, delivery channel.
  • two_fa_logs: audit log of events.

Testing Locally

  • Enable mail logging (e.g., MAIL_MAILER=log) to see email messages in logs.
  • For SMS/WhatsApp, just bind callbacks that Log::info() the outbound text.

License

Apache-2.0