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 Two Factor Auth Laravel Package

vormkracht10/filament-two-factor-auth

Adds two-factor authentication to Filament panels. Users enable TOTP through authenticator apps with QR codes and recovery codes, while admins can enforce 2FA panel-wide for stronger login security.

View on GitHub
Deep Wiki
Context7

Getting Started

v3.0.0 is a breaking release: the package moved to the Backstage organisation and the PHP namespace changed to Backstage\.... Treat this as a fresh install rather than a patch bump.

Minimal setup on a Filament panel:

  1. Install the v3 package (verify the Composer name in the README — it follows the repo move to backstagephp/filament-2fa; if your composer.json still points at the old vendor, swap it before running composer update).
  2. Publish and run the migration — the package needs the Fortify-style columns on your authenticatable table:
    $table->text('two_factor_secret')->nullable();
    $table->text('two_factor_recovery_codes')->nullable();
    $table->timestamp('two_factor_confirmed_at')->nullable();
    
  3. Wire up the User model — implement the package's 2FA contract and pull in its trait:
    use Backstage\Filament2fa\Contracts\TwoFactorAuthentication;
    use Backstage\Filament2fa\Traits\TwoFactorAuthenticatable;
    
    class User extends Authenticatable implements FilamentUser, TwoFactorAuthentication
    {
        use TwoFactorAuthenticatable;
    }
    
    Double-check every use Baspa\... / old-namespace import in your app — these are the lines that break on upgrade.
  4. Register the plugin in the panel provider:
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugin(TwoFactor::make());
    }
    
  5. Publish config, translations and views, then clear caches (config:clear, optimize:clear, filament:optimize-clear).

Where to look first: the plugin class and its fluent API (it's where enforcement, branding/icon, and page registration live), then config/filament-2fa.php. First use case: lock down an admin panel so every user must enrol a TOTP app before reaching any resource — enable it on your most privileged panel only, and roll out to staff before customers.

Implementation Patterns

Per-panel registration, not global. Register TwoFactor::make() only on panels that need it (e.g. AdminPanelProvider), and leave the public/customer panel alone unless required. This keeps the login redirect behaviour scoped and makes it trivial to A/B the rollout.

Enforcement vs. self-service. Two distinct flows you'll typically ship together:

  • Enforcement — the plugin intercepts panel access for users without two_factor_confirmed_at and pushes them through setup. Ideal for internal/admin panels.
  • Self-service — expose the 2FA setup/recovery-code page from the user menu or a profile page so users can enable, disable, or regenerate recovery codes on their own time.

Multi-guard / multi-model apps. If you have separate User and Admin models, implement the 2FA contract on each and add the columns to each table. Do not attempt to share the trait across guards with a single config entry.

Onboarding existing users. For a live app, don't flip enforcement to "on" repo-wide in one deploy. Ship the plugin with self-service enabled first, email/nudge users, then enable enforcement per panel. Users with two_factor_confirmed_at = null are the ones the middleware will redirect, so that column is your rollout dashboard — User::whereNull('two_factor_confirmed_at')->count().

Recovery codes are the support path. Store them encrypted (the trait handles this), never log them, and give support a documented process: user loses their phone → admin clears two_factor_secret / two_factor_recovery_codes / two_factor_confirmed_at via tinker or an admin action, user re-enrols. Build that reset action early; it's the #1 2FA support ticket.

Translations. v3 adds German and fixes translation overriding. If you run a non-English panel, publish the package translations and override keys in lang/vendor/... rather than editing vendor files — the override fix in this release makes published overrides take effect reliably, so re-check any language files you'd previously worked around.

Testing. In feature tests, either create users with two_factor_confirmed_at set, or disable enforcement for the test panel in TestCase/phpunit.xml. Always include one test that asserts an unenrolled user is redirected away from a protected resource — that's the regression you actually care about.

Gotchas and Tips

  • Namespace rename is the whole upgrade. Baspa\... → Backstage\... touches your User model imports, panel provider plugin registration, any custom pages extending package classes, published config/view files that reference the service provider, and any container bindings or class_exists checks. Run a project-wide grep for the old namespace and the old vendor string before you composer update, and diff your published views afterwards.
  • Composer name may have changed too. Repository transfers frequently come with a package rename. If composer update resolves nothing new, confirm the require line and that composer.lock isn't pinned to the old vendor.
  • Re-publish, don't assume. Config, views and translations published under v2 may be stale or reference the old namespace. Back up your customisations, re-publish, then re-apply them.
  • The base-URL redirect loop is fixed. If your panel is mounted at /, v2 could bounce you infinitely between login and the 2FA challenge. If you previously worked around this with custom middleware, route ordering, or by moving the panel path — remove that workaround. Keeping it may now cause the loop it was patching.
  • Setup pages must be exempt from enforcement. If you write your own enforcement middleware or customise routing, make sure the 2FA setup/challenge routes and the logout route are excluded, otherwise unenrolled users hit a redirect loop and can't even sign out.
  • Login button fix. v3 restores the loading state on the login button. If you'd shipped a custom login page or a patched view to compensate, drop it and re-test with slow network throttling.
  • Never trust the secret column shape. Confirm it's text/longText — encrypted values are long, and a truncated varchar(255) produces "MAC is invalid" decryption errors that look like a config problem but are a schema problem.
  • Queue/session side effects. Enabling enforcement invalidates the experience for impersonating admins and API-token flows. Decide explicitly whether impersonation bypasses 2FA (usually it should, but log it), and keep non-panel API auth on a separate guard.
  • Cache after deploy. Filament caches components and the panel config; a namespace change plus stale caches yields "class not found" on a page that plainly exists. Always php artisan optimize:clear && php artisan filament:optimize-clear as the first debugging step — before you start reading stack traces.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo