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 2Fa Laravel Package

vormkracht10/filament-2fa

Adds two-factor authentication to Filament panels. Users can enable TOTP with authenticator apps via QR code and use recovery codes. Includes a profile page and middleware to enforce 2FA for admin access.

View on GitHub
Deep Wiki
Context7

Getting Started

Upgrading from v2.x is the first task for existing users. v3.0.0 is a breaking release: the package namespace changed to Backstage (and the repo moved to backstagephp/filament-2fa). Before touching any feature work:

composer require backstage/filament-2fa:^3.0

Then sweep your codebase for the old namespace in:

  • use statements in any custom page, middleware, listener, or service provider that references package classes (e.g. Baspa\FilamentTwoFactor\... → Backstage\FilamentTwoFactor\...)
  • Published config (config/filament-2fa.php) — re-publish with --force and diff, since class references inside it may have moved
  • Published views/translations that @extends or use package classes
  • Any composer.json replace/alias entries or autoload overrides pointing at the old vendor name
php artisan vendor:publish --tag="filament-2fa-config" --force
php artisan vendor:publish --tag="filament-2fa-lang" --force   # see Gotchas: translation resolution changed
php artisan optimize:clear

New installs: install, publish config + migrations, migrate, then register the plugin on the panel you want protected:

use Backstage\FilamentTwoFactor\FilamentTwoFactorPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(FilamentTwoFactorPlugin::make());
}

Where to look first: the published config (which drivers/options exist for the second factor and recovery codes), then the package's src/Pages/ for the challenge/setup pages, then your users table migration — 2FA state is column-based on the authenticatable model, so the migration is the thing that will bite you in production.

First use case: protect a single admin panel behind TOTP, let users enrol via a profile/security page, and hand out recovery codes at enrolment time. Do this end-to-end in staging against a copy of real user data before enabling enforcement.

Implementation Patterns

Panel-scoped rollout. Register the plugin only on sensitive panels (admin/staff), leaving customer-facing panels untouched. Because it's a panel plugin, you can gate enforcement per-panel rather than globally, which keeps blast radius small.

Enrolment + enforcement as separate phases. Ship in "optional" mode first: users see a setup prompt but can skip. Once enrolment rate is acceptable, flip enforcement on. Use the package's middleware/guard behaviour for enforcement and a Filament notification or banner to nag unenrolled users in the interim.

Challenge before the panel boots. The 2FA challenge needs to intercept the login flow, so it interacts with panel path resolution and the login route. If your panel is mounted at the domain root (->path('')), v3.0.0 fixes the infinite-redirect loop that v2.x had — this is the one bug fix most likely to unblock a previously broken deployment. Verify your root-path panel actually reaches the challenge page and not a redirect cycle.

Custom user model integration. The trait/interface is applied to your User model. If you use a non-standard authenticatable (separate Admin model, multi-guard setup), implement the contract on each model and confirm the migration columns exist on every table involved. Multi-guard auth is the most common place this package needs bespoke wiring.

Recovery codes as an operational concern. Generate and display them once, hashed at rest. Provide a documented "lost device" path — either an admin CLI/artisan command or a Filament action on the user resource that resets 2FA state, plus an audit trail. Without this, support requests become manual DB edits.

Testing. Use Filament::setCurrentPanel() + acting-as in feature/HTTP tests. Store a known TOTP secret on the factory user state and compute codes with a TOTP library in the test, rather than mocking the package internals. Cover: unenrolled user hits challenge → redirected to setup; enrolled user with valid code → panel loads; invalid code → throttled; recovery code consumed exactly once.

Deployment/CI. php artisan config:cache will freeze any 2FA config you read at runtime — re-run after config changes. Add a smoke test for the login flow in CI so a namespace or route regression from this major bump fails the build, not production.

Gotchas and Tips

The namespace change is the whole risk of this release. It is a string-level breaking change that PHP won't catch until runtime for anything resolved dynamically — config arrays with ::class strings, published views, container bindings in your own service providers, cached config from your last deploy. composer dump-autoload plus a grep for the old vendor/namespace is mandatory. Grep storage/framework/cache indirectly by clearing caches, not by editing them.

Translation overrides now resolve differently. PR #88 fixed translation override behaviour. If you previously published lang/vendor/... files to customise copy, re-publish in v3 and re-apply your edits — your old override may now be silently ignored, or a package string may suddenly win over yours. Check the login/challenge screens in a non-English locale after upgrading; German translations also landed, so de users will see different strings than before.

Login button loading state was fixed (#91). If you had a custom login view or JS patch working around the missing loading indicator, remove it — it can now double-fire or conflict with the package's own state handling.

Base-URL panel path redirect loop (#83). Only relevant if your panel path is the base URL. If you previously worked around it with a custom middleware or a non-empty path prefix, revert that workaround before testing, or you'll conclude the fix doesn't work when it's your workaround causing the symptom.

Debugging a stuck challenge loop. Use php artisan route:list filtered to your panel to confirm the challenge route resolves under the expected path, and check storage/logs/laravel.log for redirect loops. APP_URL mismatch behind a proxy/load balancer is the usual culprit for 2FA redirects bouncing.

Extension points to prefer. Subclass the package's setup/challenge pages and point the config at your subclass rather than editing published views — view edits are the first casualty of any namespace or markup change. Same for translations: prefer a targeted override key over a wholesale copy of the lang file.

Pin the major version. "backstage/filament-2fa": "^3.0" — any future namespace or config-key reshuffle is a major, and this project has already demonstrated it will make those. Add the package to your upgrade-watch list; the repo transfer to backstagephp means issue/PR links in old docs and blog posts now 404.

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.
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
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin