NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Every event lives in RoundlyConsulting\TwoFactor\Events and carries the user model as $user — never a secret or a code. A few add a non-sensitive detail:

EventFired whenPayload
TwoFactorEnrolmentStartedstart() persists a fresh pending secret.user
TwoFactorConfirmedconfirm() enables 2FA.user
TwoFactorDisableddisable() clears all two-factor state.user
RecoveryCodesRegeneratedrecoveryCodes()->regenerate() replaces the code set.user
RecoveryCodeConsumedattempt() burns a recovery code; remaining is the count left.user, remaining
TwoFactorVerifiedA user passes a challenge, via TwoFactorMethod::Totp or ::RecoveryCode.user, method
TwoFactorVerificationFailedAn enrolled user fails a challenge — not on a replay, not for a user without a secret.user
TwoFactorReplayDetectedA code whose timestep was already used is rejected.user, timestep
TwoFactorRateLimitedThe built-in limiter locks a user out.user, secondsUntilAvailable

Listening

TwoFactorVerified and TwoFactorVerificationFailed let you audit challenges, meter success and failure rates, and drive host-side lockout without wrapping the facade — for example a listener that increments a rate limiter:

use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\RateLimiter;
use RoundlyConsulting\TwoFactor\Events\TwoFactorVerificationFailed;

Event::listen(function (TwoFactorVerificationFailed $event): void {
    RateLimiter::hit("2fa:{$event->user->getKey()}");
});

Enrolment, disabling, recovery-code use and replay attempts are all announced too, so you can feed them into an audit log or alerting without extra plumbing.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.