scheb/2fa-google-authenticator
Adds Google Authenticator-based two-factor authentication (TOTP) to Symfony apps. Generates QR codes and secrets, validates one-time codes, and plugs into your login flow to improve account security with minimal setup.
Installation:
composer require scheb/2fa-google-authenticator
Ensure scheb/2fa-bundle is also installed (this package extends it).
Configuration:
Add the bundle to config/bundles.php:
Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true],
Enable in Security:
In config/packages/security.yaml, add:
firewalls:
main:
form_login:
provider: app_user_provider
two_factor: ~ # Enables 2FA
First Use Case:
use Scheb\TwoFactorBundle\Generator\GoogleAuthenticatorGenerator;
$generator = new GoogleAuthenticatorGenerator();
$secret = $generator->generateSecret();
user.two_factor_secret).Scheb\TwoFactorBundle\Generator\GoogleAuthenticatorGenerator::getQRCodeImageAsDataUri()).User Onboarding:
<img src="{{ app.user.two_factor_qr_code }}" alt="QR Code">
Login Flow:
# config/routes.yaml
two_factor_login:
path: /login-2fa
controller: Scheb\TwoFactorBundle\Controller\TwoFactorController::checkCode
TwoFactorValidator:
$validator = $this->container->get('scheb_two_factor.validator');
if (!$validator->validateCode($user, $code)) {
// Handle failure (e.g., retry or fallback).
}
Fallback Mechanisms:
TwoFactorAuthenticatorInterface to customize fallback logic.API Integration:
TwoFactorGuard to protect routes:
use Symfony\Component\HttpFoundation\Request;
use Scheb\TwoFactorBundle\Security\TwoFactorGuard;
$guard = $this->container->get('security.guard.two_factor');
if (!$guard->checkCode($user, $request->request->get('code'))) {
throw new \RuntimeException('Invalid 2FA code');
}
Database Schema:
Add a two_factor_secret column to your users table (e.g., VARCHAR(32) for Base32 secrets).
Example migration:
Schema::table('users', function (Blueprint $table) {
$table->string('two_factor_secret')->nullable()->after('password');
});
User Interface: Use the bundle’s Twig helpers to display QR codes and forms:
{{ scheb_two_factor_qr_code(user.two_factor_secret) }}
{{ scheb_two_factor_form(user) }}
Testing:
Mock the GoogleAuthenticatorGenerator and TwoFactorValidator in unit tests:
$validator = $this->createMock(TwoFactorValidator::class);
$validator->method('validateCode')->willReturn(true);
$this->container->set('scheb_two_factor.validator', $validator);
Secret Storage:
two_factor_secret in the database if your application handles sensitive data.Time Synchronization:
Scheb\TwoFactorBundle\Generator\GoogleAuthenticatorGenerator::checkCode() to manually verify codes during development.Session Management:
Rate Limiting:
RateLimiter:
# config/packages/security.yaml
firewalls:
main:
two_factor:
rate_limiter: 'authentication.two_factor'
services:
authentication.two_factor:
class: Symfony\Component\Security\Http\RateLimiter\RateLimiter
arguments:
- '@security.http_utils'
- 5 # Max attempts
- 60 # Time window (seconds)
Backup Codes:
TwoFactorAuthenticatorInterface or a separate table for backup codes.Invalid Codes:
two_factor_secret is correctly stored and not corrupted.$generator = new GoogleAuthenticatorGenerator();
$generator->checkCode($user->two_factor_secret, $code);
# config/packages/scheb_two_factor.yaml
scheb_two_factor:
debug: true
QR Code Issues:
$secret = rtrim(strtr(base64_encode(random_bytes(10)), '+/', '-_'), '=');
$generator = new GoogleAuthenticatorGenerator();
$qrCodeUrl = $generator->getQRCodeImageAsDataUri('[email protected]', $secret);
Custom Authenticators:
Extend Scheb\TwoFactorBundle\Security\TwoFactorAuthenticator\TwoFactorAuthenticatorInterface to support additional providers (e.g., Authy, YubiKey).
Event Listeners:
Listen to scheb_two_factor.on_code_verified or scheb_two_factor.on_code_failed to trigger custom logic (e.g., logging, notifications):
use Scheb\TwoFactorBundle\Event\TwoFactorEvent;
$dispatcher->addListener(TwoFactorEvent::CODE_VERIFIED, function (TwoFactorEvent $event) {
// Log successful 2FA.
});
Configuration Overrides:
Override default settings in config/packages/scheb_two_factor.yaml:
scheb_two_factor:
google_authenticator:
window: 1 # Allow 1 code window (default: 1)
issuer: 'MyApp' # Custom issuer name for QR code
CSRF Protection: Ensure 2FA forms include CSRF tokens. The bundle auto-generates tokens for Twig forms, but manually rendered forms require:
{{ form_start(form, { 'attr': {'novalidate': 'novalidate'} }) }}
{{ form_widget(form._token) }}
How can I help you explore Laravel packages today?