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

eddusoft/filament-access-control-2fa

Filament plugin that adds access control with two-factor authentication, helping you secure admin panels and manage user permissions. Extend Filament resources and panels with 2FA challenges and role-based access restrictions, keeping sensitive areas protected while staying simple to configure.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a Filament panel plugin that bolts TOTP 2FA and access control onto an existing Filament panel. It assumes you already have Filament v3 installed and working — do not attempt to bootstrap a project from this package alone. At v1.0.1 the identity of the package is still moving (the release note is literally "Change the package name to publish it"), so treat install as an exploratory step, not a production commitment.

Minimal setup sequence:

  1. Pin the exact tag. Floating constraints are unsafe here given the rename in v1.0.1. In composer.json:

    "require": {
        "eddusoft/filament-access-control-2fa": "1.0.1"
    }
    

    Do not assume the old v1.0.0 name resolves. If you previously installed v1.0.0, remove that requirement first, composer clear-cache, then require the new name.

  2. Verify auto-discovery. After composer install, check bootstrap/cache/packages.php contains the (new) provider. If not, run php artisan package:discover. On any deploy pipeline that ships a prebuilt cache, force a rebuild rather than a restart — a stale cache silently disables the plugin and you get "class not found" at request time.

  3. Publish config and migrations. Read the README for the exact tags — Filament package conventions usually give you something like:

    php artisan vendor:publish --tag="filament-access-control-2fa-config"
    php artisan vendor:publish --tag="filament-access-control-2fa-migrations"
    php artisan migrate
    

    Verify the tags against the repo — they may embed the old name if the rename was metadata-only.

  4. Register the plugin on the panel in your PanelProvider:

    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugin(FilamentAccessControl2FaPlugin::make());
    }
    
  5. Wire the user model. Whatever contract the package expects (an interface/trait, or a configurable enforce_2fa flag) needs to be applied to your User model. This is the step most likely to break if the package assumed a specific user model shape.

First use case to prove out: a single admin user enables 2FA via the Filament profile page, scans the QR with an authenticator app, gets recovery codes shown once, logs out, and logs back in completing the TOTP challenge. If that loop doesn't close cleanly in half a day, stop — this is the whole value of the package.

Implementation Patterns

Panel-level enforcement is the primary day-to-day lever. Once registered, a panel ->plugin(...) call is the single point where 2FA gets switched on for that panel's users. Keep it in the dedicated PanelProvider (AdminPanelProvider, StaffPanelProvider) rather than a global provider so you can roll it out panel-by-panel — e.g. admins get enforcement day one, an internal tools panel stays opt-in.

Role-based enforcement. "Enforcement options for users, roles, or panels" means you'll want a pattern like:

  • a config or DB flag keyed on role (works well alongside spatie/laravel-permission)
  • a per-user "must enroll" boolean for break-glass exceptions
  • panel-level hard enforcement for the highest-risk panel

Wrap the role lookup behind your own helper (User::requiresTwoFactor()) rather than scattering permission checks through Filament resources — you want exactly one place to change the policy.

Opt-in enrollment flow for users who aren't enforced: a Filament page/action that shows the QR + secret, then requires the user to submit a valid code before persisting the secret. Persisting on QR display alone is the classic bug — a user scans nothing, closes the tab, and is locked out next login.

Recovery codes: generate on enrollment, display exactly once, store hashed (or at minimum encrypted). Standard pattern:

  • N codes (commonly 8), shown once with a download / copy button
  • single-use: mark consumed on redeem
  • "regenerate" action that invalidates the whole prior set

If the package doesn't do hashing or single-use out of the box, add it at your boundary — don't trust the default.

Access control integration. Two separate uses:

  1. Coarse — who can reach the panel at all. This should sit above (or alongside) Filament's canAccessPanel(), not replace it.
  2. Fine — resource-level canAccess() / policies for sensitive resources (billing, user management). Keep policies as the source of truth; treat this package's access control as an additional gate, not a shadow authorization system.

Testing pattern. The non-negotiable workflow for a day-to-day package like this:

  • Use pestphp/pest-plugin-livewire or Filament's own testing helpers to click through the Filament login flow.
  • Freeze time ($this->travelTo(...)) so TOTP windows are deterministic.
  • Generate valid codes in tests via a direct TOTP helper (pragmarx/google2fa or otplib/spomky-labs/otphp) using the user's stored secret, rather than mocking the package's internals.
  • Write one integration test at the boundary: "user with 2FA enabled cannot reach /admin without TOTP; user who redeems a recovery code can." That single test is your alarm when a patch release breaks the contract.

Feature-flag it. Given the v1.0.x churn, put the plugin registration behind a config flag or your own thin TwoFactorGate interface. If the package is abandoned or the API shifts, removing it becomes a config flip plus deleting one test.

Gotchas and Tips

The rename is the first gotcha, not the last. v1.0.1 changed the Composer package name in a patch release. That means:

  • If both old and new names end up in the dependency graph, you get duplicate provider registration and class-redeclaration fatals. Audit composer show for both.
  • Internal docs, runbooks, allowlists, and CI caches keyed on the old name must be updated in the same change window.
  • The PSR-4 namespace may or may not have moved. Grep use statements after upgrading if you consumed v1.0.0.

Clearing caches after every install/upgrade:

php artisan config:clear
php artisan cache:clear
php artisan view:clear
composer dump-autoload
php artisan package:discover

Missing any of these is the #1 cause of "the plugin is installed but nothing renders."

TOTP clock skew. Authenticator apps and server clocks drift. Most TOTP libraries accept ±1–2 windows by default; if users report "invalid code" on otherwise-correct apps, widen the verification window (config knob) before touching anything else. Never widen past ±2 — it materially weakens the second factor.

Lockout is the top operational risk. Enforce 2FA and you will eventually lock out an admin. Plan for it before rollout:

  • a documented recovery-code regeneration path via php artisan tinker or a custom command
  • a 2fa:disable {user} artisan command you own, not trusting the package to ship one
  • a break-glass super-admin whose 2FA state you can reset out-of-band

Enrollment must be verified, not just initiated. Confirm the user submitted a valid code before persisting the secret. This is the single most common 2FA integration defect.

Recovery code edge cases:

  • Consume on use (single-use). If the package stores them in plaintext or allows reuse, fix it.
  • Normalize input — users paste codes with spaces/dashes.
  • Show them exactly once. A "view recovery codes" page after the fact means you're storing them recoverably; if that's a requirement, encrypt, don't hash.

Filament version drift. Filament v3 plugin APIs (the Plugin contract, panel ->plugin(), profile page composition) changed from v2. Confirm the package targets v3 specifically. If the README doesn't state a Laravel major / Filament major matrix, assume nothing beyond your own installed versions and pin accordingly.

Extension points to prefer. Where the package exposes hooks (config keys, a customizable User contract, events for TwoFactorEnabled / RecoveryCodeUsed), hook into them instead of overriding the package's pages or extending its internals. You'll survive a v1.0.2 bump; a forked page class you won't.

Logging and observability. Log enrollment, disable, and recovery-code-use events at info with the user id. When someone claims they got locked out or their codes were used, this is the only evidence you'll have.

Watch the repo, not just the tag. Score of 0.7 and 0 stars means this is likely a single-author, pre-traction package. Set a GitHub release-watch or a calendar reminder to re-check before you depend on it beyond a pilot. Two consecutive substantive patch releases with no identity churn is your signal to promote it past staging.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource