webmonks / laravel-2fa
🔐 Plug & Play Laravel 2FA - Email OTP, SMS OTP, TOTP, WebAuthn/FIDO2, Recovery Codes with Multi-Auth Guard Support. Production-ready in 30 seconds!
Requires
- php: ^8.1
- ext-ldap: *
- ext-openssl: *
- bacon/bacon-qr-code: ^2.0
- doctrine/dbal: ^3.0
- firebase/php-jwt: ^6.10
- folklore/graphql: ^5.0|^6.0
- illuminate/auth: ^10.0|^11.0|^12.0
- illuminate/config: ^10.0|^11.0|^12.0
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/encryption: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/mail: ^10.0|^11.0|^12.0
- illuminate/notifications: ^10.0|^11.0|^12.0
- illuminate/queue: ^10.0|^11.0|^12.0
- illuminate/session: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- illuminate/validation: ^10.0|^11.0|^12.0
- laravel/passport: ^11.0|^12.0
- league/fractal: ^0.20
- league/oauth2-client: ^2.7
- nyholm/psr7: ^1.8
- onelogin/php-saml: ^4.1
- phpseclib/phpseclib: ^3.0
- pragmarx/google2fa: ^8.0
- pusher/pusher-http-php: ^7.2
- pusher/pusher-php-server: ^7.2
- ramsey/uuid: ^4.7
- rebing/graphql-laravel: ^9.0
- spatie/laravel-query-builder: ^5.0
- spatie/laravel-rate-limiting: ^2.0
- web-auth/webauthn-lib: ^4.9
Requires (Dev)
- mockery/mockery: ^1.4
- nunomaduro/collision: ^7.0|^8.0
- orchestra/testbench: ^8.0|^9.0|^10.0
- pestphp/pest: ^2.36
- pestphp/pest-plugin-laravel: ^2.0
- phpunit/phpunit: ^10.0
Suggests
- aws/aws-sdk-php: Required for SMS OTP functionality via AWS SNS (^3.0)
- google/apiclient: Google Workspace SSO integration (^2.15)
- microsoft/azure-activedirectory-library-for-php: Azure AD integration support (^1.0)
- symfony/ldap: Enhanced LDAP support for Active Directory integration (^6.0|^7.0)
- twilio/sdk: Required for SMS OTP functionality via Twilio (^7.0)
- vonage/client: Required for SMS OTP functionality via Vonage/Nexmo (^4.0)
This package is auto-updated.
Last update: 2025-09-26 05:29:29 UTC
README
The definitive Laravel 2FA package with true plug-and-play architecture. Zero configuration required - works instantly with Laravel Mail, then scales to enterprise needs with WhatsApp, Voice, Push Notifications, and custom delivery providers.
Transform your Laravel authentication from basic to bulletproof in 30 seconds. Unlike other 2FA packages that force you into rigid patterns, Laravel 2FA v1.1 gives you the freedom to start simple and customize everything as your requirements evolve - now with global reach through WhatsApp, Voice calls, Push notifications, and intelligent fallback systems.
Why Laravel 2FA?
🚀 30-Second Setup: Install, migrate, protect routes - done. Email OTP works immediately with your existing Laravel Mail configuration.
🔌 True Plug & Play: Start with zero configuration, then customize anything. No vendor lock-in, no forced dependencies, no architectural constraints.
🎯 Production Battle-Tested: 96 comprehensive tests, 227 assertions, extensive security features, and real-world deployment experience.
🏗️ Enterprise-Ready Architecture: Multi-auth support, device trust management, comprehensive rate limiting, audit logging, and extensible provider system.
Key Features
🔐 Complete 2FA Methods
- Email OTP (zero-config) - Works instantly with Laravel Mail
- SMS OTP - Twilio, Vonage/Nexmo, AWS SNS with fallback chains
- WhatsApp OTP - Twilio WhatsApp & WhatsApp Business API
- Voice Call OTP - Multi-language voice calls with customizable voices
- Push Notifications - FCM (Android/iOS/Web) & APNS (iOS) with approval workflows
- TOTP/Google Authenticator - Time-based codes with QR generation
- Recovery Codes - Secure backup authentication system
🛡️ Enterprise Security
- Multi-Auth Guards: Native support for web, admin, api, customer - any authentication guard
- Advanced Fallback System: Multi-provider chains with intelligent failover
- Device Trust Management: Remember trusted devices with configurable expiration
- Rate Limiting: Brute force protection with configurable thresholds
- End-to-End Encryption: All sensitive data encrypted at rest
- Comprehensive Audit Logging: Track all 2FA events and security incidents
🔧 Developer Experience
- True Plug & Play: Works in 30 seconds with zero configuration
- 100% Customizable: Override providers, templates, logic, UI - or use sensible defaults
- Custom Delivery Providers: Slack, Discord, Telegram integration examples
- Extensible Architecture: Create custom providers for any delivery method
- 95%+ Test Coverage: Production-ready with PestPHP testing framework
- Laravel 10, 11, 12+ Ready: Modern Laravel compatibility with future-proof architecture
Requirements
- PHP: 8.1+ minimum
- Laravel: 10.0+ (supports 11.x, 12.x)
- Optional Providers: Twilio SDK, Vonage, AWS SNS, FCM, APNS for enhanced 2FA methods
Quick Start (30 Seconds)
1. Install & Setup
composer require webmonks/laravel-2fa php artisan two-factor:install php artisan migrate
2. Prepare Your User Model
<?php namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use WebMonks\Laravel2FA\Contracts\TwoFactorAuthenticatable; use WebMonks\Laravel2FA\Traits\HasTwoFactorAuthentication; class User extends Authenticatable implements TwoFactorAuthenticatable { use HasTwoFactorAuthentication; // Your existing model code... }
3. Protect Routes & Enable 2FA
// Protect routes (in routes/web.php) Route::group(['middleware' => ['auth', '2fa']], function () { Route::get('/dashboard', [DashboardController::class, 'index']); Route::get('/sensitive-data', [DataController::class, 'show']); }); // Enable 2FA for users (in your controller) use WebMonks\Laravel2FA\Facades\TwoFactor; // Email OTP (works immediately - zero configuration needed) TwoFactor::enable($user, 'email'); // TOTP/Google Authenticator TwoFactor::enable($user, 'totp'); $qrCodeUrl = TwoFactor::getTotpQrCodeUrl($user); // Show this QR to user
That's it! Your routes are now protected with email-based 2FA using Laravel's built-in mail system.
Zero Configuration Philosophy
Laravel 2FA works instantly with your existing setup, then grows with your needs:
// Day 1: Email OTP (works immediately) TwoFactor::enable($user, 'email'); TwoFactor::generateCode($user, 'email'); // Sends via Laravel Mail // Day 30: Add SMS when ready // .env: TWILIO_SID=xxx TWILIO_TOKEN=yyy TWILIO_FROM=+1234567890 TwoFactor::setPhoneNumber($user, '+15551234567'); TwoFactor::enable($user, 'sms'); // Day 60: Add WhatsApp for global users TwoFactor::enable($user, 'whatsapp'); TwoFactor::generateCode($user, 'whatsapp'); // Day 90: Add Voice calls for accessibility TwoFactor::enable($user, 'voice'); TwoFactor::generateCode($user, 'voice'); // Multi-language support // Day 120: Add Push notifications for mobile apps TwoFactor::enable($user, 'push'); TwoFactor::registerPushDevice($user, $fcmToken, 'android'); // Day 150: Add TOTP for power users TwoFactor::enable($user, 'totp'); $qrCode = TwoFactor::getTotpQrCodeUrl($user); // Day 180: Add device trust and recovery codes $recoveryCodes = TwoFactor::generateRecoveryCodes($user); TwoFactor::trustDevice($user, $deviceFingerprint);
Complete Installation Guide
Basic Installation
# Install the package composer require webmonks/laravel-2fa # Run installation (publishes config, migrations) php artisan two-factor:install # Run migrations php artisan migrate
Optional: Publish Configuration
# Publish config for customization (optional) php artisan vendor:publish --tag=two-factor-config # Publish views for UI customization (optional) php artisan vendor:publish --tag=two-factor-views
Optional: SMS Provider Setup
For Twilio (Recommended)
composer require twilio/sdk
# .env TWO_FACTOR_SMS_ENABLED=true TWILIO_SID=your_account_sid TWILIO_TOKEN=your_auth_token TWILIO_FROM=+15551234567
For Vonage/Nexmo
composer require vonage/client
# .env TWO_FACTOR_SMS_ENABLED=true TWO_FACTOR_SMS_DRIVER=vonage VONAGE_API_KEY=your_api_key VONAGE_API_SECRET=your_api_secret VONAGE_FROM=YourApp
For AWS SNS
composer require aws/aws-sdk-php
# .env TWO_FACTOR_SMS_ENABLED=true TWO_FACTOR_SMS_DRIVER=aws-sns AWS_ACCESS_KEY_ID=your_access_key AWS_SECRET_ACCESS_KEY=your_secret_key AWS_DEFAULT_REGION=us-east-1
Usage Examples
Email OTP (Zero Configuration)
use WebMonks\Laravel2FA\Facades\TwoFactor; // Enable email 2FA (works immediately with Laravel Mail) TwoFactor::enable($user, 'email'); // Generate and send code TwoFactor::generateCode($user, 'email'); // User receives: "Your verification code is: 123456" // Verify code $isValid = TwoFactor::verifyCode($user, '123456', 'email'); // Check status $isEnabled = TwoFactor::isEnabled($user, 'email');
SMS OTP (Once Provider Configured)
// Set user's phone number TwoFactor::setPhoneNumber($user, '+15551234567'); // Enable SMS 2FA TwoFactor::enable($user, 'sms'); // Generate and send SMS $sent = TwoFactor::generateCode($user, 'sms'); if ($sent) { return response()->json(['message' => 'SMS sent to your phone']); } // Verify SMS code $isValid = TwoFactor::verifyCode($user, $request->input('code'), 'sms');
TOTP/Google Authenticator
// Enable TOTP TwoFactor::enable($user, 'totp'); // Get QR code URL for setup $qrCodeUrl = TwoFactor::getTotpQrCodeUrl($user); // Display this QR code to user for scanning with Google Authenticator // Get setup key (alternative to QR code) $setupKey = TwoFactor::getTotpSecretKey($user); // Verify TOTP code $isValid = TwoFactor::verifyCode($user, '123456', 'totp');
Recovery Codes
// Generate recovery codes $codes = TwoFactor::generateRecoveryCodes($user); // Returns: ['a1b2c3d4e5', 'f6g7h8i9j0', ...] (8 codes by default) // Show codes to user for safe storage foreach ($codes as $code) { echo "Recovery code: {$code}\n"; } // Verify recovery code $isValid = TwoFactor::verifyRecoveryCode($user, 'a1b2c3d4e5'); // Check remaining recovery codes $remaining = TwoFactor::getRemainingRecoveryCodes($user);
Device Trust Management
// Generate device fingerprint (your implementation) $deviceFingerprint = hash('sha256', $request->ip() . $request->userAgent()); // Trust current device TwoFactor::trustDevice($user, $deviceFingerprint); // Check if device is trusted if (TwoFactor::isDeviceTrusted($user, $deviceFingerprint)) { // Skip 2FA for trusted device return redirect('/dashboard'); } // Remove trusted device TwoFactor::removeTrustedDevice($user, $deviceFingerprint); // Get all trusted devices $trustedDevices = TwoFactor::getTrustedDevices($user);
New in v1.1: Advanced 2FA Methods
Laravel 2FA v1.1 introduces powerful new authentication methods for enhanced security and global reach.
WhatsApp OTP
Send verification codes via WhatsApp using Twilio WhatsApp or WhatsApp Business API.
Configuration
For Twilio WhatsApp:
# Install Twilio SDK
composer require twilio/sdk
# .env TWO_FACTOR_WHATSAPP_ENABLED=true TWILIO_SID=your_account_sid TWILIO_TOKEN=your_auth_token TWILIO_WHATSAPP_FROM=whatsapp:+14155238886
For WhatsApp Business API:
# .env TWO_FACTOR_WHATSAPP_ENABLED=true TWO_FACTOR_WHATSAPP_DRIVER=whatsapp_business WHATSAPP_BUSINESS_ACCESS_TOKEN=your_access_token WHATSAPP_BUSINESS_PHONE_NUMBER_ID=your_phone_number_id WHATSAPP_BUSINESS_API_VERSION=v18.0
Usage
use WebMonks\Laravel2FA\Facades\TwoFactor; // Set user's WhatsApp number TwoFactor::setPhoneNumber($user, '+15551234567'); // Enable WhatsApp 2FA TwoFactor::enable($user, 'whatsapp'); // Generate and send WhatsApp code $sent = TwoFactor::generateCode($user, 'whatsapp'); if ($sent) { return response()->json(['message' => 'WhatsApp code sent successfully']); } // Verify WhatsApp code $isValid = TwoFactor::verifyCode($user, $request->input('code'), 'whatsapp'); // Custom message template $messageTemplate = 'Your *{app_name}* verification code is: *{code}*\n\nExpires in {expiry_minutes} minutes. 🔐';
Voice Call OTP
Deliver verification codes via voice calls with multi-language support and customizable voices.
Configuration
# .env TWO_FACTOR_VOICE_ENABLED=true TWILIO_SID=your_account_sid TWILIO_TOKEN=your_auth_token TWILIO_VOICE_FROM=+15551234567 # Voice settings TWO_FACTOR_VOICE_LANGUAGE=en-US TWO_FACTOR_VOICE_TYPE=woman TWO_FACTOR_VOICE_SPEED=1.0 TWO_FACTOR_VOICE_REPEAT_COUNT=2
Usage
// Enable voice call 2FA TwoFactor::enable($user, 'voice'); // Generate and make voice call $called = TwoFactor::generateCode($user, 'voice'); if ($called) { return response()->json(['message' => 'Voice call initiated']); } // Verify voice code $isValid = TwoFactor::verifyCode($user, $request->input('code'), 'voice'); // Supported languages and voices $languages = ['en-US', 'es-ES', 'fr-FR', 'de-DE', 'it-IT', 'pt-BR', 'ru-RU', 'ja-JP', 'ko-KR', 'zh-CN']; $voices = ['woman', 'man', 'alice']; // Alice supports more languages
Additional SMS Providers
Enhanced SMS support with Vonage (formerly Nexmo) and AWS SNS, plus intelligent fallback chains.
Vonage/Nexmo Configuration
# Install Vonage SDK
composer require vonage/client
# .env TWO_FACTOR_SMS_ENABLED=true TWO_FACTOR_SMS_DRIVER=vonage VONAGE_API_KEY=your_api_key VONAGE_API_SECRET=your_api_secret VONAGE_FROM=YourApp
AWS SNS Configuration
# Install AWS SDK
composer require aws/aws-sdk-php
# .env TWO_FACTOR_SMS_ENABLED=true TWO_FACTOR_SMS_DRIVER=aws-sns AWS_ACCESS_KEY_ID=your_access_key AWS_SECRET_ACCESS_KEY=your_secret_key AWS_DEFAULT_REGION=us-east-1 AWS_SNS_SENDER_ID=YourApp
SMS Provider Fallback
Configure fallback chains for maximum reliability:
// config/two-factor.php 'sms' => [ 'driver' => 'twilio', 'fallback_drivers' => ['vonage', 'aws-sns'], // Fallback order // Additional fallback settings 'fallback_delay' => 30, // Wait 30s before trying fallback 'max_fallback_attempts' => 2, ],
// Usage remains the same - fallback is automatic TwoFactor::generateCode($user, 'sms'); // Will try Twilio → Vonage → AWS SNS
Push Notifications
Implement push notification-based 2FA with approval workflows for mobile applications.
FCM (Firebase Cloud Messaging) Configuration
# .env TWO_FACTOR_PUSH_ENABLED=true TWO_FACTOR_PUSH_DRIVER=fcm FCM_SERVER_KEY=your_server_key FCM_SENDER_ID=your_sender_id FCM_PROJECT_ID=your_project_id FCM_CREDENTIALS_FILE=/path/to/service-account.json
APNS (Apple Push Notification) Configuration
# .env TWO_FACTOR_PUSH_ENABLED=true TWO_FACTOR_PUSH_DRIVER=apns APNS_KEY_ID=your_key_id APNS_TEAM_ID=your_team_id APNS_APP_BUNDLE_ID=com.yourapp.bundle APNS_PRIVATE_KEY_PATH=/path/to/AuthKey_XXXXX.p8 APNS_PRODUCTION=false
Push Notification Usage
// Register user's push device TwoFactor::registerPushDevice($user, $fcmToken, 'android', [ 'device_name' => 'John\'s iPhone', 'device_model' => 'iPhone 13', 'app_version' => '1.2.0', ]); // Enable push 2FA TwoFactor::enable($user, 'push'); // Send push notification for approval $sent = TwoFactor::generateCode($user, 'push'); if ($sent) { return response()->json([ 'message' => 'Push notification sent', 'timeout' => 300, // 5 minutes to approve ]); } // Check approval status $isApproved = TwoFactor::isPushApproved($user, $challengeId); // Approve push notification (from mobile app) TwoFactor::approvePushChallenge($user, $challengeId, [ 'biometric_used' => true, 'location' => ['lat' => 37.7749, 'lng' => -122.4194], 'device_info' => ['battery' => 85, 'network' => 'wifi'], ]); // Deny push notification TwoFactor::denyPushChallenge($user, $challengeId, 'User denied');
Custom Delivery Providers
Extend Laravel 2FA with custom delivery methods like Slack, Discord, or Telegram.
Slack Integration Example
# .env TWO_FACTOR_CUSTOM_DELIVERY_ENABLED=true SLACK_2FA_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz SLACK_2FA_CHANNEL=#security SLACK_2FA_USERNAME=2FA Bot
// Create custom Slack provider class SlackTwoFactorProvider extends AbstractCustomProvider { public function send(string $to, string $message, array $options = []): bool { $payload = [ 'channel' => $this->config['channel'] ?? '#security', 'username' => $this->config['username'] ?? '2FA Bot', 'text' => "🔐 2FA Code for {$to}: `{$message}`", 'icon_emoji' => ':lock:', ]; return Http::post($this->config['webhook_url'], $payload)->successful(); } } // Register in service provider $this->app->bind('two-factor.custom.slack', SlackTwoFactorProvider::class); // Usage TwoFactor::enableCustomDelivery($user, 'slack', ['channel' => '@john.doe']); TwoFactor::generateCode($user, 'slack');
Discord Integration Example
# .env DISCORD_2FA_WEBHOOK_URL=https://discord.com/api/webhooks/xxx/yyy DISCORD_2FA_USERNAME=2FA Bot
class DiscordTwoFactorProvider extends AbstractCustomProvider { public function send(string $to, string $message, array $options = []): bool { $payload = [ 'username' => $this->config['username'] ?? '2FA Bot', 'content' => "🔒 **2FA Verification Code**\nUser: {$to}\nCode: `{$message}`\n⏰ Expires in 10 minutes", 'embeds' => [[ 'color' => 0x00ff00, 'title' => '🔐 Two-Factor Authentication', 'description' => "Your verification code: **{$message}**", 'timestamp' => now()->toISOString(), ]], ]; return Http::post($this->config['webhook_url'], $payload)->successful(); } }
Telegram Bot Integration
# .env TELEGRAM_BOT_TOKEN=your_bot_token TELEGRAM_CHAT_ID=your_chat_id
class TelegramTwoFactorProvider extends AbstractCustomProvider { public function send(string $to, string $message, array $options = []): bool { $payload = [ 'chat_id' => $this->config['chat_id'], 'text' => "🔐 *2FA Verification Code*\n\nUser: {$to}\nCode: `{$message}`\n\n⏰ Expires in 10 minutes", 'parse_mode' => 'Markdown', 'reply_markup' => json_encode([ 'inline_keyboard' => [[ ['text' => '✅ Approved', 'callback_data' => "approve_{$message}"], ['text' => '❌ Deny', 'callback_data' => "deny_{$message}"], ]], ]), ]; $url = "https://api.telegram.org/bot{$this->config['bot_token']}/sendMessage"; return Http::post($url, $payload)->successful(); } }
Advanced Fallback Configuration
Configure sophisticated fallback chains for maximum delivery reliability.
// config/two-factor.php 'custom_delivery' => [ 'fallback_chain' => [ 'enabled' => true, 'primary_to_fallback_delay' => 30, // seconds 'chains' => [ // SMS fallback chain 'sms_fallback' => ['sms', 'whatsapp', 'voice', 'email'], // Email fallback chain 'email_fallback' => ['email', 'push'], // Push fallback chain 'push_fallback' => ['push', 'sms', 'email'], // Custom enterprise chain 'enterprise_fallback' => ['push', 'whatsapp', 'voice', 'slack', 'email'], ], ], ],
// Automatic fallback usage TwoFactor::enableFallbackChain($user, 'enterprise_fallback'); TwoFactor::generateCode($user, 'sms'); // Will try entire enterprise chain if needed
Environment Variables for v1.1 Features
# WhatsApp Configuration TWO_FACTOR_WHATSAPP_ENABLED=false TWO_FACTOR_WHATSAPP_DRIVER=twilio TWILIO_WHATSAPP_FROM=whatsapp:+14155238886 WHATSAPP_BUSINESS_ACCESS_TOKEN=your_token WHATSAPP_BUSINESS_PHONE_NUMBER_ID=your_phone_id # Voice Call Configuration TWO_FACTOR_VOICE_ENABLED=false TWILIO_VOICE_FROM=+15551234567 TWO_FACTOR_VOICE_LANGUAGE=en-US TWO_FACTOR_VOICE_TYPE=woman TWO_FACTOR_VOICE_SPEED=1.0 # Additional SMS Providers TWO_FACTOR_SMS_DRIVER=twilio TWO_FACTOR_SMS_FALLBACK_DRIVERS=vonage,aws-sns VONAGE_API_KEY=your_api_key VONAGE_API_SECRET=your_api_secret AWS_SNS_SENDER_ID=YourApp # Push Notifications TWO_FACTOR_PUSH_ENABLED=false TWO_FACTOR_PUSH_DRIVER=fcm FCM_SERVER_KEY=your_server_key FCM_PROJECT_ID=your_project_id APNS_KEY_ID=your_key_id APNS_TEAM_ID=your_team_id APNS_APP_BUNDLE_ID=com.yourapp.bundle # Custom Delivery TWO_FACTOR_CUSTOM_DELIVERY_ENABLED=false SLACK_2FA_WEBHOOK_URL=https://hooks.slack.com/services/xxx DISCORD_2FA_WEBHOOK_URL=https://discord.com/api/webhooks/xxx TELEGRAM_BOT_TOKEN=your_bot_token TELEGRAM_CHAT_ID=your_chat_id # Advanced Settings TWO_FACTOR_FALLBACK_CHAIN_ENABLED=false TWO_FACTOR_FALLBACK_DELAY=30
Multi-Auth Guard Support
Laravel 2FA natively supports multiple authentication guards for complex applications:
Configuration
// config/two-factor.php 'guards' => [ 'web' => [ 'enabled' => true, 'model' => \App\Models\User::class, 'routes' => [ 'challenge' => '/two-factor/challenge', 'verify' => '/two-factor/verify', ], ], 'admin' => [ 'enabled' => true, 'model' => \App\Models\Admin::class, 'routes' => [ 'challenge' => '/admin/two-factor/challenge', 'verify' => '/admin/two-factor/verify', ], ], 'api' => [ 'enabled' => true, 'model' => \App\Models\User::class, 'stateless' => true, // No sessions for API ], 'customer' => [ 'enabled' => true, 'model' => \App\Models\Customer::class, 'routes' => [ 'challenge' => '/customer/two-factor/challenge', 'verify' => '/customer/two-factor/verify', ], ], ],
Usage with Guards
// Enable 2FA for different guards TwoFactor::enable($user, 'email', 'web'); TwoFactor::enable($admin, 'totp', 'admin'); TwoFactor::enable($customer, 'sms', 'customer'); // Guard-specific middleware Route::group(['middleware' => ['auth:admin', '2fa:admin']], function () { Route::get('/admin/dashboard', [AdminController::class, 'dashboard']); }); Route::group(['middleware' => ['auth:customer', '2fa:customer']], function () { Route::get('/customer/profile', [CustomerController::class, 'profile']); }); // API routes with stateless 2FA Route::middleware(['auth:sanctum', '2fa:api'])->group(function () { Route::get('/api/user', function (Request $request) { return $request->user(); }); }); // Verify codes with specific guard $isValid = TwoFactor::verifyCode($admin, $code, 'totp', 'admin'); $isValid = TwoFactor::verifyCode($user, $code, 'email', 'api');
Advanced Features
Rate Limiting & Security
// Built-in rate limiting (configurable) 'rate_limiting' => [ 'enabled' => true, 'max_attempts' => 5, // 5 attempts 'decay_minutes' => 15, // per 15 minutes ], // SMS-specific rate limiting 'sms' => [ 'rate_limiting' => [ 'per_phone_number' => [ 'max_attempts' => 10, // 10 SMS per phone 'decay_minutes' => 60, // per hour ], 'global' => [ 'max_attempts' => 1000, // 1000 SMS total 'decay_minutes' => 60, // per hour ], ], ],
Audit Logging
// Enable comprehensive logging 'logging' => [ 'enabled' => true, 'channel' => 'stack', // Uses Laravel's logging 'events' => [ 'enabled' => true, // Log when 2FA enabled 'disabled' => true, // Log when 2FA disabled 'verified' => true, // Log successful verifications 'failed' => true, // Log failed attempts 'recovery_used' => true, // Log recovery code usage ], ],
Custom Email Templates
// Publish views for customization php artisan vendor:publish --tag=two-factor-views // Customize email templates in: // resources/views/vendor/two-factor/emails/code.blade.php // resources/views/vendor/two-factor/emails/code-text.blade.php
Custom SMS Provider
<?php namespace App\Providers\Sms; use WebMonks\Laravel2FA\Contracts\SmsProvider; use WebMonks\Laravel2FA\Providers\Sms\AbstractSmsProvider; class CustomSmsProvider extends AbstractSmsProvider { public function send(string $to, string $message, array $options = []): bool { // Your custom SMS logic here $response = Http::post('https://api.yoursms.com/send', [ 'api_key' => $this->config['api_key'], 'to' => $to, 'message' => $message, ]); return $response->successful(); } public function getName(): string { return 'custom'; } public function getMaxMessageLength(): int { return 160; } public function getRequiredConfig(): array { return ['api_key', 'api_secret']; } }
Register in your service provider:
// AppServiceProvider.php public function register() { $this->app->bind('two-factor.sms.custom', function ($app) { $config = config('two-factor.sms.drivers.custom', []); return new CustomSmsProvider($config); }); }
API & JSON Responses
For API applications, Laravel 2FA provides structured JSON responses:
API Middleware
Route::middleware(['auth:sanctum', '2fa:api'])->group(function () { Route::get('/user', function (Request $request) { return $request->user(); }); Route::post('/sensitive-action', [ApiController::class, 'sensitiveAction']); });
JSON Response Format
When 2FA is required, the middleware returns:
{ "message": "Two-factor authentication required", "error": "two_factor_required", "available_methods": ["email", "sms", "whatsapp", "voice", "push", "totp"], "challenge_url": "/api/two-factor/challenge" }
API Endpoints
// Generate codes via API POST /api/two-factor/generate { "method": "email" // or "sms", "whatsapp", "voice", "push", "totp" } // Verify codes via API POST /api/two-factor/verify { "code": "123456", "method": "email" } // Push notification approval API POST /api/two-factor/push/approve { "challenge_id": "uuid-challenge-id", "approved": true, "biometric_used": true } // Get user 2FA status GET /api/two-factor/status
Testing
Running Tests
# Run all tests composer test # Run with coverage composer test-coverage # Run specific test suite ./vendor/bin/pest tests/Feature/EmailOtpTest.php ./vendor/bin/pest tests/Feature/SmsOtpTest.php ./vendor/bin/pest tests/Feature/TotpTest.php
Test Your Integration
use Illuminate\Support\Facades\Notification; use WebMonks\Laravel2FA\Notifications\TwoFactorSmsCode; use WebMonks\Laravel2FA\Facades\TwoFactor; public function test_email_otp_flow() { Mail::fake(); // Enable email 2FA TwoFactor::enable($this->user, 'email'); // Generate code TwoFactor::generateCode($this->user, 'email'); // Assert email was sent Mail::assertSent(TwoFactorCodeMail::class); // Verify code works $code = TwoFactor::getLastGeneratedCode($this->user, 'email'); $this->assertTrue(TwoFactor::verifyCode($this->user, $code, 'email')); } public function test_sms_otp_flow() { Notification::fake(); // Setup SMS TwoFactor::setPhoneNumber($this->user, '+15551234567'); TwoFactor::enable($this->user, 'sms'); // Generate SMS code TwoFactor::generateCode($this->user, 'sms'); // Assert SMS notification sent Notification::assertSentTo($this->user, TwoFactorSmsCode::class); }
Artisan Commands
Laravel 2FA includes helpful Artisan commands for management:
# Install package (publishes config & migrations) php artisan two-factor:install # Enable 2FA for a user php artisan two-factor:enable "App\Models\User" 1 --method=email php artisan two-factor:enable "App\Models\Admin" 5 --method=totp --guard=admin # Disable 2FA for a user php artisan two-factor:disable "App\Models\User" 1 php artisan two-factor:disable "App\Models\Admin" 5 --guard=admin # Check 2FA status php artisan two-factor:status "App\Models\User" 1 php artisan two-factor:status --all php artisan two-factor:status --guard=admin # Generate recovery codes php artisan two-factor:recovery-codes "App\Models\User" 1
Configuration Reference
Core Configuration
// config/two-factor.php 'default_method' => 'email', 'enabled_methods' => [ 'email' => true, // Email OTP (zero config) 'sms' => false, // SMS OTP (requires provider) 'totp' => true, // TOTP/Google Authenticator 'recovery_codes' => true, // Recovery codes ], 'email' => [ 'length' => 6, // Code length 'expire_minutes' => 10, // Code expiration 'throttle_minutes' => 1, // Send throttling 'max_attempts' => 5, // Max verification attempts 'queue' => 'default', // Queue for sending emails ], 'sms' => [ 'length' => 6, 'expire_minutes' => 10, 'driver' => 'twilio', // SMS provider 'message_template' => 'Your {app_name} code: {code}', ], 'totp' => [ 'issuer' => 'YourApp', // App name in authenticator 'algorithm' => 'sha1', // TOTP algorithm 'digits' => 6, // Code digits 'period' => 30, // Code validity period 'window' => 1, // Time window tolerance ], 'recovery_codes' => [ 'count' => 8, // Number of recovery codes 'length' => 10, // Recovery code length ],
Environment Variables
# Core settings TWO_FACTOR_DEFAULT_METHOD=email TWO_FACTOR_EMAIL_ENABLED=true TWO_FACTOR_SMS_ENABLED=false TWO_FACTOR_TOTP_ENABLED=true # Email settings TWO_FACTOR_EMAIL_OTP_LENGTH=6 TWO_FACTOR_EMAIL_EXPIRE_MINUTES=10 TWO_FACTOR_EMAIL_MAX_ATTEMPTS=5 # SMS settings (Twilio example) TWILIO_SID=your_account_sid TWILIO_TOKEN=your_auth_token TWILIO_FROM=+15551234567 # Rate limiting TWO_FACTOR_RATE_LIMITING_ENABLED=true TWO_FACTOR_RATE_LIMIT_MAX_ATTEMPTS=5 TWO_FACTOR_RATE_LIMIT_DECAY_MINUTES=15 # Security TWO_FACTOR_ENCRYPTION_ENABLED=true TWO_FACTOR_LOGGING_ENABLED=true TWO_FACTOR_REMEMBER_DEVICE_DAYS=30
Performance & Optimization
Queue Configuration
// Email & SMS can be queued for better performance 'email' => [ 'queue' => true, 'queue_name' => 'notifications', ], 'sms' => [ 'queue' => true, 'queue_name' => 'sms', ],
Database Optimization
// Add indexes for better performance (included in migrations) Schema::table('two_factor_auth', function (Blueprint $table) { $table->index(['user_id', 'user_type']); $table->index(['expires_at']); $table->index(['created_at']); });
Caching
// Cache TOTP secrets and settings for performance 'totp' => [ 'cache_enabled' => true, 'cache_ttl' => 3600, // 1 hour ],
Security Considerations
Data Protection
- Encryption: All sensitive data (secrets, codes) encrypted at rest
- Secure Deletion: Used codes and expired data automatically purged
- No Plain Text: Codes never stored in plain text, always hashed
- Secure Transmission: HTTPS recommended for all 2FA operations
Rate Limiting
// Multi-layer rate limiting 'rate_limiting' => [ 'global' => [ 'max_attempts' => 1000, // Global limit 'decay_minutes' => 60, ], 'per_user' => [ 'max_attempts' => 10, // Per user limit 'decay_minutes' => 60, ], 'per_ip' => [ 'max_attempts' => 50, // Per IP limit 'decay_minutes' => 60, ], ],
Best Practices
- Use HTTPS: Always serve your application over HTTPS
- Secure Sessions: Use secure session configuration
- Monitor Logs: Enable audit logging and monitor for suspicious activity
- Regular Updates: Keep the package and dependencies updated
- Backup Recovery Codes: Ensure users safely store recovery codes
- Test Thoroughly: Test 2FA flows in staging before production
Troubleshooting
Common Issues
Email OTP Not Sending
// Check Laravel Mail configuration php artisan config:cache php artisan queue:work // Test Laravel Mail directly Mail::to('test@example.com')->send(new TestMail()); // Check 2FA logs tail -f storage/logs/laravel.log | grep "2fa"
SMS Issues
// Verify SMS provider credentials php artisan tinker > config('two-factor.sms.drivers.twilio') // Test provider connection > TwoFactor::testSmsProvider('twilio') // Check phone number format > PhoneNumberFormatter::format('+1-555-123-4567', 'US')
TOTP Sync Issues
// Increase time window tolerance 'totp' => [ 'window' => 2, // Allow ±2 time periods (±60 seconds) ], // Check server time synchronization date_default_timezone_set('UTC');
WhatsApp Issues
// Test WhatsApp provider credentials php artisan tinker > config('two-factor.whatsapp.drivers.twilio') // Check WhatsApp sandbox setup (Twilio) > TwoFactor::testWhatsAppProvider('twilio') // Verify WhatsApp Business API credentials > Http::get('https://graph.facebook.com/v18.0/{phone-number-id}', [ 'access_token' => config('two-factor.whatsapp.drivers.whatsapp_business.access_token') ]);
Common WhatsApp Issues:
- Sandbox not configured: Ensure WhatsApp sandbox is properly set up in Twilio Console
- Business API not approved: WhatsApp Business API requires Meta approval for production
- Invalid phone format: WhatsApp requires E.164 format (
+1234567890
) - Template violations: Messages must follow WhatsApp template policies
Voice Call Issues
// Test voice provider > TwoFactor::testVoiceProvider('twilio') // Check voice capabilities for phone number > TwoFactor::checkVoiceCapabilities('+15551234567') // Test TwiML generation > TwoFactor::generateVoiceTwiML('123456', ['language' => 'en-US'])
Common Voice Issues:
- Number not voice-enabled: Some numbers don't support voice calls
- Language not supported: Check available languages for your region
- Audio quality issues: Adjust speed and voice type settings
- International restrictions: Some countries have voice calling restrictions
Push Notification Issues
// Test FCM credentials > TwoFactor::testFCMProvider() // Test APNS connection > TwoFactor::testAPNSProvider() // Check device registration > TwoFactor::checkPushDeviceRegistration($user, $deviceToken) // Validate push payload > TwoFactor::validatePushPayload($payload)
Common Push Issues:
- Invalid FCM server key: Ensure server key matches project
- APNS certificate expired: Check certificate validity
- Device token invalid: Tokens expire and need refresh
- Network issues: Push services require stable internet connection
- App not in foreground: Some systems require app to be active
SMS Provider Fallback Issues
// Test fallback chain > TwoFactor::testSMSFallbackChain(['twilio', 'vonage', 'aws-sns']) // Check provider status > TwoFactor::checkProviderStatus('vonage') > TwoFactor::checkProviderStatus('aws-sns') // View fallback logs > TwoFactor::getFallbackLogs($user, 'sms')
Common Fallback Issues:
- All providers failing: Check network connectivity and credentials
- Infinite fallback loops: Ensure fallback_drivers doesn't include primary driver
- Quota exceeded: Monitor usage limits for each provider
- Configuration mismatch: Verify each provider's required settings
Custom Delivery Provider Issues
// Test Slack webhook > Http::post(config('two-factor.custom_delivery.providers.slack.webhook_url'), [ 'text' => 'Test message from Laravel 2FA' ]); // Test Discord webhook > TwoFactor::testCustomProvider('discord') // Test Telegram bot > TwoFactor::testTelegramBot()
Common Custom Provider Issues:
- Webhook URL invalid: Verify webhook URLs are accessible
- Authentication failed: Check API keys and tokens
- Rate limiting: Custom providers may have rate limits
- Message formatting: Some providers require specific message formats
Debug Mode
# Enable detailed logging for all new features TWO_FACTOR_LOGGING_ENABLED=true TWILIO_DEBUG=true TWILIO_WHATSAPP_DEBUG=true TWILIO_VOICE_DEBUG=true FCM_DEBUG=true APNS_DEBUG=true VONAGE_DEBUG=true AWS_SNS_DEBUG=true LOG_LEVEL=debug # Enable test modes TWO_FACTOR_WHATSAPP_TESTING=true TWO_FACTOR_VOICE_TESTING=true TWO_FACTOR_PUSH_TESTING=true TWO_FACTOR_SMS_TESTING=true
Monitoring & Analytics
// Monitor delivery success rates $stats = TwoFactor::getDeliveryStats($user, 'last_30_days'); // Track provider performance $performance = TwoFactor::getProviderPerformance(['twilio', 'vonage', 'fcm']); // Get fallback usage statistics $fallbackStats = TwoFactor::getFallbackStatistics(); // Monitor costs (if cost tracking enabled) $costs = TwoFactor::getCostAnalysis('this_month');
Support Channels
- Documentation: Complete documentation and examples
- Issues: Bug reports and feature requests
- Questions: GitHub Issues with "question" label
- Security: Report security vulnerabilities
Roadmap
✅ Version 1.1 (Released - January 2025)
- ✅ WhatsApp OTP: Twilio WhatsApp & WhatsApp Business API integration
- ✅ Voice Call OTP: Multi-language voice calls with Twilio
- ✅ Additional SMS Providers: Vonage/Nexmo & AWS SNS support
- ✅ Push Notifications: FCM (Android/iOS/Web) & APNS (iOS) support
- ✅ Custom Delivery Providers: Slack, Discord, Telegram integration examples
- ✅ Advanced Fallback System: Multi-provider fallback chains
- ✅ Enhanced Security: Improved rate limiting and monitoring
Version 1.2 (Q2 2025)
- Admin Dashboard: Web UI for 2FA management and analytics
- Enhanced Analytics: Usage statistics, success rates, and cost tracking
- Backup Authentication: Hardware security keys (WebAuthn/FIDO2)
- Mobile SDK: React Native and Flutter SDK for push notifications
Version 2.0 (Q3 2025)
- Biometric Support: Touch ID, Face ID integration
- Risk-Based Authentication: AI-powered adaptive authentication
- Multi-Tenant Support: SaaS application features
- Advanced Audit: Compliance reporting and forensic analysis
Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
git clone https://github.com/webmonks-technologies/laravel-2fa.git
cd laravel-2fa
composer install
cp .env.example .env
./vendor/bin/pest
Code Standards
- PSR-12: Follow PSR-12 coding standards
- Tests: All features must include tests
- Documentation: Update docs for new features
- Backwards Compatibility: Maintain BC unless major version
Security Vulnerabilities
If you discover a security vulnerability, please send an email to darshan@webmonks.in. All security vulnerabilities will be promptly addressed.
License
Laravel 2FA is open-sourced software licensed under the MIT License.
Credits
- WebMonks Team: Core maintainers
- Contributors: All amazing contributors
- Inspiration: Built on the shoulders of giants in the Laravel ecosystem
Ready to secure your Laravel application?
composer require webmonks/laravel-2fa php artisan two-factor:install php artisan migrate
From zero to bulletproof authentication in 30 seconds. 🚀