Installation
composer require hydrat-agency/laravel-2fa
php artisan vendor:publish --provider="HydratAgency\Laravel2FA\Laravel2FAServiceProvider"
php artisan migrate
config/2fa.php) and creates the two_factor_tokens table.Enable for a User
use HydratAgency\Laravel2FA\Facades\Laravel2FA;
// Generate and send a 2FA token (e.g., via email/SMS)
Laravel2FA::generateAndSendToken($user);
First Use Case: Login Flow
Laravel2FA::check() middleware in your Authenticate middleware group:
$middleware->append(\HydratAgency\Laravel2FA\Middleware\CheckTwoFactor::class);
Token Generation & Delivery
Notifiable) or SMS (via Nexmo/Vonage).HydratAgency\Laravel2FA\Notifications\TwoFactorToken:
class CustomTokenNotification extends TwoFactorToken {
public function via($notifiable) {
return ['slack', 'custom_webhook'];
}
}
config/2fa.php:
'notification' => \App\Notifications\CustomTokenNotification::class,
Conditional Checks
TrustedDevicePolicy):
use HydratAgency\Laravel2FA\Contracts\TwoFactorPolicy;
class TrustedDevicePolicy implements TwoFactorPolicy {
public function applies($user, $request) {
return $request->ip() === $user->trusted_ip;
}
}
config/2fa.php:
'policies' => [
\HydratAgency\Laravel2FA\Policies\TrustedDevicePolicy::class,
\App\Policies\TrustedDevicePolicy::class,
],
Manual Verification
if (Laravel2FA::shouldCheck($user, $request)) {
$token = Laravel2FA::generateAndSendToken($user);
return redirect()->route('verify.2fa')->with('token', $token);
}
Token Validation
if (Laravel2FA::verifyToken($user, $request->input('token'))) {
// Grant access or proceed
}
CheckTwoFactor middleware after authentication but before session creation.ThrottleRequests to rate-limit 2FA attempts:
Route::middleware(['throttle:6,1'])->group(function () {
Route::post('/verify', [TwoFactorController::class, 'verify']);
});
public function applies($user, $request) {
return !$user->is_super_admin;
}
Token Expiry
config/2fa.php token_lifetime).Laravel2FA::setTokenLifetime($user, 30); // 30 minutes
Database Locks
DB::transaction(function () use ($user) {
Laravel2FA::generateAndSendToken($user);
});
Notification Failures
try {
Laravel2FA::generateAndSendToken($user);
} catch (\Exception $e) {
Log::error("2FA Notification Failed: " . $e->getMessage());
session()->flash('2fa_fallback', true);
}
Middleware Order
CheckTwoFactor before Authenticate will block all unauthenticated users.$middleware->append(\App\Http\Middleware\Authenticate::class);
$middleware->append(\HydratAgency\Laravel2FA\Middleware\CheckTwoFactor::class);
two_factor_tokens table for stale entries:
SELECT * FROM two_factor_tokens WHERE expires_at < NOW();
config(['2fa.policies' => []]);
TwoFactorGenerated events to debug token delivery:
Laravel2FA::listen(function ($user, $token) {
Log::debug("Token for {$user->email}: {$token}");
});
Custom Drivers
HydratAgency\Laravel2FA\Contracts\TokenDriver:
class RedisTokenDriver implements TokenDriver {
public function store($userId, $token, $expiresAt) {
Redis::set("2fa:{$userId}", $token, 'EX', $expiresAt->timestamp);
}
// Implement other methods...
}
config/2fa.php:
'driver' => \App\Services\RedisTokenDriver::class,
Dynamic Policies
class DynamicTrustedPolicy implements TwoFactorPolicy {
public function applies($user, $request) {
$trustedIps = $this->fetchTrustedIpsFromAPI($user);
return in_array($request->ip(), $trustedIps);
}
}
Backup Codes
$codes = Laravel2FA::generateBackupCodes($user, 5); // 5 backup codes
Laravel2FA::storeBackupCodes($user, $codes);
TokenGenerator. Override by extending the class.ShouldQueue:
class TwoFactorToken implements ShouldQueue {
public function handle() {
// Retry on failure
$this->notify($this->notifiable);
}
}
How can I help you explore Laravel packages today?