scheb/2fa-email
Adds email-based two-factor authentication to Symfony apps using Scheb’s 2FA bundle. Generates and delivers one-time codes via email, supports custom mailers/templates, code validation and trusted devices, for an extra login security layer.
Installation
composer require scheb/2fa-email
Ensure scheb/2fa-bundle is already installed (this package extends it).
Configuration
Add to your config/2fa.php:
'providers' => [
'email' => [
'enabled' => true,
'template' => 'emails.two_factor_auth_code', // Customize in resources/views
],
],
First Use Case Trigger 2FA for a user:
use Scheb\TwoFactorBundle\Security\TwoFactorAuthenticatorInterface;
$authenticator = $this->get('scheb_two_factor.authenticator');
$code = $authenticator->generateCode(); // Generates a 6-digit code
$authenticator->sendEmailCode($user, $code); // Sends email with code
Verify Code
$isValid = $authenticator->checkCode($user, $inputCode);
Enable 2FA for New Users
// In User registration controller
$user->setTwoFactorEnabled(true);
$user->save();
$authenticator->sendEmailCode($user, $authenticator->generateCode());
Post-Registration Redirect
return redirect()->route('verify.2fa.email')->with('user', $user);
Verification Blade Template
<form method="POST" action="{{ route('verify.2fa.email') }}">
@csrf
<input type="text" name="code" placeholder="6-digit code">
<button type="submit">Verify</button>
</form>
Custom Guard Extension
Extend SchebTwoFactorGuard in config/guard.php:
'guards' => [
'web' => [
'provider' => 'users',
'authenticator' => 'scheb_two_factor.authenticator',
],
],
Middleware for Protected Routes
use Scheb\TwoFactorBundle\Security\TwoFactorMiddleware;
protected $middleware = [
TwoFactorMiddleware::class,
];
Session-Based Code Storage Store the code in the user’s session after generation:
$request->session()->put('2fa_email_code', $code);
Override Email Template Publish the template:
php artisan vendor:publish --tag=scheb-two-factor-email-templates
Modify resources/views/vendor/scheb_two_factor/email/code.txt.twig.
Dynamic Recipient Logic
Override Scheb\TwoFactorBundle\Security\EmailAuthenticator:
public function sendCode(UserInterface $user, $code)
{
Mail::to($this->getCustomEmail($user))->send(new TwoFactorEmail($code));
}
protected function getCustomEmail(User $user)
{
return $user->alternateEmail ?: $user->email;
}
Rate Limiting
$authenticator->sendEmailCode($user, $code)->onQueue('emails');
Session Expiry
$request->session()->forget(['2fa_email_code', '2fa_email_attempts']);
Testing
Scheb\TwoFactorBundle\Security\EmailAuthenticator in tests:
$this->partialMock(EmailAuthenticator::class, ['sendCode']);
Configuration Overrides
scheb/2fa-bundle is configured before scheb/2fa-email in config/2fa.php to avoid provider conflicts.Check Logs
Enable debug mode in config/2fa.php:
'debug' => env('APP_DEBUG', false),
Logs will appear in storage/logs/laravel.log.
Verify Email Dispatch Use Laravel’s mail preview:
php artisan mail:preview Scheb\TwoFactorBundle\Mail\TwoFactorEmail --code=123456
Common Issues
MAIL_DRIVER in .env (must be smtp, mailgun, etc.).user_id is correctly stored in the session.Custom Providers
Extend Scheb\TwoFactorBundle\Security\Provider\EmailProvider to add:
Event Listeners
Listen for scheb.two_factor.code.sent and scheb.two_factor.code.verified:
Event::listen('scheb.two_factor.code.sent', function ($user, $code) {
// Log or notify admins
});
API Integration For SPAs, return the code via API:
Route::post('/2fa/email/send', function (Request $request) {
$authenticator = app(EmailAuthenticator::class);
$code = $authenticator->generateCode();
$authenticator->sendCode($request->user(), $code);
return response()->json(['status' => 'sent']);
});
How can I help you explore Laravel packages today?