chillerlan/php-authenticator
PHP 8.4+ library to generate and verify HOTP (RFC 4226) and TOTP (RFC 6238) one-time passwords, compatible with Google Authenticator-style apps. Includes optional Steam Guard time sync plus constant-time encoding helpers for safer key handling.
AuthenticatorInterface), making it easy to swap implementations (e.g., for testing or future upgrades).VerifyTwoFactorChallenge.user table or encrypted sessions table.secret (base32-encoded string) and optionally a counter (for HOTP) or last_used_at (for TOTP) field per user.Authenticator instance per request is efficient.| Risk Area | Mitigation Strategy |
|---|---|
| PHP 8.4 Dependency | Laravel 10+ supports PHP 8.4; downgrade risk is low if using older Laravel. |
| Sodium Extension | Fallback to paragonie/constant_time_encoding ensures compatibility. |
| Secret Storage | Secrets must be base32-encoded and stored securely (e.g., encrypted DB field). |
| Time Sync (TOTP) | useLocalTime option allows fallback to server time if client time is unreliable. |
| HOTP Counter Drift | Requires careful DB design (e.g., auto-incrementing counter or manual updates). |
| Algorithm Downgrades | SHA1 is deprecated; enforce SHA256/SHA512 via AuthenticatorOptions. |
Mode Selection:
Secret Storage:
users table, Redis, or a dedicated otp_secrets table?)users table with a secret column (base32) and otp_mode (TOTP/HOTP).Verification Flow:
Fallback Mechanisms:
throttle middleware and add backup code support.Testing:
Authenticator::createSecret() in tests with fixed time offsets.VerifyTwoFactorChallenge with custom logic using chillerlan/php-authenticator.TwoFactorGuard middleware to validate OTPs before issuing tokens.ext-curl (for Steam Guard), ext-sodium (preferred) or paragonie/constant_time_encoding.endroid/qr-code (for QR code generation in user onboarding).Phase 1: Setup
composer.json:
"require": {
"chillerlan/php-authenticator": "^5.4"
}
secret and otp_mode fields to the users table:
Schema::table('users', function (Blueprint $table) {
$table->string('otp_secret')->nullable();
$table->enum('otp_mode', ['totp', 'hotp'])->default('totp')->nullable();
$table->integer('otp_counter')->nullable(); // For HOTP
});
Phase 2: User Onboarding
/setup-2fa) that:
$authenticator->createSecret().getUri()) and manual entry fallback.Phase 3: Verification Logic
public function verifyTwoFactorChallenge(Request $request)
{
$user = User::find($request->user());
$authenticator = new Authenticator(
new AuthenticatorOptions(['mode' => $user->otp_mode]),
$user->otp_secret
);
if ($authenticator->verify($request->input('code'))) {
// Success: regenerate session or issue token.
}
return back()->withErrors(['code' => 'Invalid OTP.']);
}
public function authenticate(Request $request)
{
$user = User::find($request->user());
$authenticator = new Authenticator(
new AuthenticatorOptions(['mode' => $user->otp_mode]),
$user->otp_secret
);
if (!$authenticator->verify($request->code)) {
throw new \Illuminate\Auth\AuthenticationException;
}
return $this->createToken($user);
}
Phase 4: HOTP Support (Optional)
users table with otp_counter.$authenticator->verify($request->code, $user->otp_counter);
$user->increment('otp_counter'); // After successful verification.
^5.3 (PHP 8.1+).config('features.2fa') to toggle 2FA during rollout.chillerlan/php-authenticator and optional QR libraries.curl_close() deprecation)./rotate-2fa-secret) to revoke compromised secrets.AuthenticatorOptions via config:
'auth' => [
'otp' => [
'algorithm' => 'SHA256', // Force SHA256/SHA512
],
],
useLocalTime: false and sync server time.periodHow can I help you explore Laravel packages today?