alt-design/alt-google-2fa-addon
Add Google two-factor authentication to your control panel logins. Users pair an authenticator app by scanning a QR code, then enter a six-digit code at sign-in—a simple, strong second layer of protection that fits into the existing login flow.
This is a Statamic addon, not a general Laravel package. Its blast radius is the Statamic Control Panel login; if your app uses plain Laravel auth, Fortify, or Breeze, this is the wrong dependency. Your day-to-day interaction is Composer + a published config file + a handful of Artisan cache commands — you will rarely write code against it.
Install and inspect
composer require alt-design/alt-google-2fa-addon
php artisan vendor:publish --provider="AltDesign\AltGoogle2fa\ServiceProvider"
Publish tags vary between addons; if --tag= guesses fail, run php artisan vendor:publish interactively and pick the addon's provider. The service provider is the real documentation here — read it first to see exactly what it registers (middleware on the CP route group, listeners on Statamic's auth events, Blade views for enrolment). Two minutes there saves an hour of guessing.
Where to look first, in order
vendor/alt-design/alt-google-2fa-addon/src/ServiceProvider.php — what it hooks into the CP auth pipeline.config/alt-google-2fa.php (name may differ) — enforcement flags, issuer name, window/discrepancy tolerance, view overrides.routes/ and resources/views/ — enrolment screen and any verification endpoints.two_factor_* stored fields, sometimes a migration).First use case
Log into the CP as a super user, open your own profile/security area, enable 2FA, scan the QR with Google Authenticator (or 1Password/Authy — all TOTP), confirm the 6-digit code, then store recovery codes somewhere durable. Verify the full loop before exposing it to editors: enrol → log out → log in → submit a wrong code → submit a correct code → use a recovery code.
Clear caches immediately after install or any config edit
php artisan config:clear && php artisan cache:clear && php artisan statamic:stache:clear
Statamic caches config and the Stache aggressively. "The addon does nothing" is, in practice, almost always a stale cache.
Config is your integration surface. Treat the published config as the API. Most behaviour — enforce vs. opt-in, role scoping, TOTP window, issuer label, view paths — lives there rather than in code. Commit it to the repo and drive it from env so local, staging, and production differ without code changes:
// config/alt-google-2fa.php
'enabled' => env('ALT_2FA_ENABLED', true),
'enforced' => env('ALT_2FA_ENFORCED', false), // false locally, true in prod
Then in .env:
ALT_2FA_ENABLED=true
ALT_2FA_ENFORCED=false # local, testing
Progressive rollout, not a flag day. Enable and enforce for super users first, exercise enrolment and login in staging, announce to editors, then flip enforcement. Enforcing before anyone knows how to enrol produces a support queue on morning one. The usual sequence: opt-in for admins → verify coverage → enforced for admins → enforced for all CP users.
Test strategy. Keep enforcement off in testing (or seed users as already-enrolled) so you don't have to drive a TOTP flow through every feature test. When you do test the flow, freeze time so the generated code is deterministic within its window:
Carbon::setTestNow('2026-01-01 12:00:00');
// generate a code with the same secret + timestamp the addon will verify
If the addon registers middleware on CP routes, your existing CP feature tests will start failing once enforcement is on — that's the signal to seed enrolment in your test user factory.
Deployment wiring. Order matters: env vars in place → php artisan config:cache → php artisan statamic:stache:clear. Back up the database (and storage/) before the first enforced deploy, because the enrolled-secret state is user data you cannot regenerate for them.
Extending it. Standard Laravel extension points work: publish and override the addon's Blade views if you need branding on the QR screen, and hook Statamic's user/auth events (Statamic\Events\UserAuthenticated, or the addon's own events if it fires them) if you want to audit enrolments into your own log or table. If enforcement semantics don't fit your policy (e.g. you need per-role enforcement and the config only supports a global boolean), the clean escape hatch is a small custom middleware that delegates to the addon's verification service rather than forking the package.
Lockout runbook, written before rollout. Have the reset path decided and documented: recovery codes for the user, and for you a break-glass via Tinker that clears the 2FA fields on the user record so they can re-enrol:
php artisan tinker
>>> $u = \Statamic\Facades\User::findByEmail('[email protected]');
>>> $u->remove('two_factor_secret')->remove('two_factor_confirmed_at')->save();
Field names depend on how the addon stores state — confirm them in the service provider or a dd($user->data()) before you rely on this in an incident.
APP_KEY rotation is a mass lockout. If the TOTP secret is stored encrypted (Laravel encrypter), rotating APP_KEY makes every secret undecryptable and forces re-enrolment for all users. Only rotate with a planned migration, or accept the reset.composer why-not statamic/cms; a pinned older Statamic is nearly always the culprit. Check the resolved matrix in composer.lock rather than assuming the constraint widened only as far as you've tested.timedatectl / NTP on the server and on the user's phone before debugging anything else. Some configs let you widen the discrepancy window — widening it permanently is a mild security regression, so prefer fixing time.config:clear → cache:clear → statamic:stache:clear. This is the number one false-positive bug report.php artisan serve login is noise that pushes developers to disable the addon, which is exactly what you don't want. Gate enforcement behind an env flag defaulting to off in local and testing.How can I help you explore Laravel packages today?