Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Multi 2Fa Laravel Package

mix-code/filament-multi-2fa

Filament Multi 2FA brings flexible two-factor authentication to Filament panels. Let users secure logins with TOTP apps, email verification codes, or recovery codes, with easy setup, multiple drivers, and per-panel configuration for admin and user-facing apps.

View on GitHub
Deep Wiki
Context7

Getting Started

mix-code/filament-multi-2fa is a Filament plugin that adds multi-device two-factor authentication (TOTP-style authenticator apps) to a panel. The "multi" is the point: a user can enroll more than one authenticator device — a phone plus a hardware key or tablet — rather than being locked to a single shared secret. That matters for shared admin accounts, ops teams, and anyone who has ever lost a phone and a recovery sheet on the same day.

Minimal path to a working setup:

  1. composer require mix-code/filament-multi-2fa — pin it ("^1.3") rather than floating, given the maintainer footprint.
  2. Register the plugin on the panel you want protected in your PanelProvider (e.g. ->plugin(FilamentMulti2FA::make())). Verify the exact factory name against the package's src/ — the README's class name is the one thing most likely to have drifted.
  3. Publish and run migrations if the package stores devices/secrets in its own table (php artisan vendor:publish --tag=... then php artisan migrate). Check whether it instead reuses a column on users — that decision changes your rollout plan.
  4. Attach the package's trait/contract to your User model (or FilamentUser implementation) so it can resolve enrolled devices.
  5. Create a throwaway user, enroll two devices, and log in with each.

Look first at the migration (what gets persisted, and whether secrets are encrypted at rest) and the login challenge class. Those two files tell you more about operational risk than the README does.

First real use case: onboarding a second admin to an existing account. Enroll device A, confirm the challenge works, then enroll device B and confirm both work independently. That is precisely the flow v1.3.0 claims to have fixed — validate it before trusting it in production.

Implementation Patterns

Trait on the model, plugin on the panel. The conventional split is: the model trait owns device state (enroll, revoke, verify), the panel plugin owns UI and the login challenge. Keep them separate in your head — when a user reports "my authenticator stopped working," you need to know whether to debug the model relation or the Filament page.

Guard-scope deliberately. If you have an admin panel and a customer-facing app panel, register the plugin only where 2FA is mandatory. Enabling it globally and then trying to exempt customers via policy is the painful direction.

Named devices. Multi-device only pays off if devices are distinguishable. Surface a label ("iPhone — Sarah", "YubiKey — ops safe") at enrollment so the revocation UI is usable six months later. If the package doesn't offer a name field, add one via a migration and a small form extension rather than shipping an anonymous device list.

Enforce-after-enrollment, not at-first-login. The smoothest rollout is: existing users log in normally, get a dismissible prompt, enroll within N days, then enforcement flips on. A hard challenge on day one generates a support queue of locked-out users and no way to verify they can complete enrollment.

Support/break-glass flow. Write it down before launch. Typically: an artisan command or admin action that clears a user's devices, gated behind your highest role, plus an audit log entry. Without this, a lost device becomes a database query written under pressure. Test the break-glass path — an untested recovery route is worse than none, because it creates false confidence.

Recovery codes are a separate artifact. If the package issues them, treat them as a second credential: hashed at rest, shown once, regenerable. If it doesn't, that's a gap you should fill rather than assume away.

Testing. Feature-test the challenge: unauthenticated request to a protected route redirects to the challenge, a valid TOTP passes, an invalid one doesn't, and a revoked device is rejected. Freeze time (Carbon::setTestNow) so TOTP windows are deterministic — flaky 2FA tests are almost always clock drift, not logic.

Upgrade pattern. Given the small maintainer base, treat minor bumps as reviewable changes: read the diff, run your suite on staging against a copy of production data, and confirm users with more than one enrolled device still authenticate after deploy.

Gotchas and Tips

v1.3.0 is a bugfix, not a feature release — but it's the version to adopt. "Fixing Multi Device Support" implies earlier releases had broken behavior when more than one device was enrolled: likely a query returning the first secret, a first() where a where() was needed, or device rows overwriting each other on save. If you ran 1.2.x with multi-device in production, audit existing enrollments — a user who "successfully" added a second device on the old version may have silently clobbered the first secret. Re-verify affected users rather than assuming the fix retroactively repairs stored state.

Thin release notes = read the diff. A one-line changelog with no migration guidance means you cannot infer whether the fix touched the schema. Check git diff v1.2.1..v1.3.0 for migration files before deploying. If a column was added, php artisan migrate is mandatory and the failure mode on forgetting it is an exception on the login path — the worst place to discover a missing column.

New contributor, first PR. @moaalaa's first contribution landed in a security-adjacent path. That's normal for small packages, but it argues for pinning exact versions, keeping a fork or patch ready, and not being the first to deploy a release to production on release day.

Config cache. After publishing config or changing panel registration, run php artisan config:clear / optimize:clear. Filament plugin registration not "taking effect" is nearly always a stale cached config in local dev.

Secrets at rest. Confirm the package encrypts TOTP secrets (Laravel encrypted cast or equivalent). If it stores plaintext, add the cast yourself — a leaked users table otherwise hands out working 2FA codes, which is the exact scenario 2FA exists to prevent.

Clock skew. TOTP verification windows are narrow. Document that server time must be NTP-synced; a drifting container produces intermittent "invalid code" reports that look like a plugin bug and aren't.

Logout/session hygiene. Decide whether disabling a device invalidates the user's active sessions. Most packages don't do this by default — a user who revokes a lost phone but stays logged in elsewhere is still exposed.

Extension points. Before hacking the vendor directory, check for publishable views and the Filament render hooks. The challenge page and device-management page are usually overridable; a published view is a maintainable fork, a patched vendor/ file is a future outage.

Compatibility pinning. Verify the package's supported Filament major in composer.json before upgrading Filament. Filament majors move fast, and small plugins lag — a Filament bump that silently breaks the login challenge is a total admin lockout, so test panel auth explicitly on any Filament upgrade.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings