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 Loginguard Laravel Package

solution-forest/filament-loginguard

Filament plugin that adds login guard and session management to your panel: track active devices, spot suspicious sign-ins, and let users review or revoke other sessions from a simple account page.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish the package assets:

composer require solution-forest/filament-loginguard
php artisan vendor:publish --tag="filament-loginguard-config"
php artisan vendor:publish --tag="filament-loginguard-migrations"
php artisan migrate

Register the plugin on the panel(s) where users should manage their devices:

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

Then expose the "My Devices" page — either via the plugin's navigation registration or by adding it to the user menu, depending on how your panel is organized.

Where to look first:

  1. The published config (config/filament-loginguard.php) — it controls the device/session model, page registration, and which panels get the UI.
  2. The service class behind the "This isn't me" action — this is the code that performs revocation, and it's the thing you should call rather than reimplementing. As of v0.7.1 it is the only supported entry point: it wraps session deletion + identity/trust changes in a transaction and enforces the current-session guard.
  3. The migration that adds trusted_at (and the device↔session mapping table). Understanding this schema is what makes the rest of the package predictable.

First use case: a user loses a laptop, logs in from a new browser, opens "My Devices", sees the old session, and clicks "This isn't me". After v0.7.1 that click now actually deletes the underlying Laravel session row, so the stolen browser is logged out on its next request instead of merely disappearing from the list.

Implementation Patterns

Treat the revocation service as the public API. Don't delete device rows or session rows yourself. If you need revocation from an admin panel, an artisan command, or a support tool, resolve the service and call it — you get the transaction, the trusted_at reset, and the 403 guard for free. Hand-rolled Model::delete() calls will reintroduce exactly the bug v0.7.1 fixed.

Handle the current-session 403 explicitly. The service now refuses to revoke the device mapped to the current session. In your UI, disable or hide the revoke action for the row flagged as the current device; in any non-Filament caller, catch the authorization exception and surface it as a validation-style message rather than a 500.

Pair "This isn't me" with a password/2FA re-confirmation. The flow is a security-sensitive action triggered by someone who may already be authenticated as the victim. Gate the action behind ->requiresConfirmation() plus a password challenge (->form() with current_password rule or your 2FA challenge), so a hijacked session can't silently nuke the legitimate user's devices.

Listen for revocation to notify the user. Fire-and-forget notifications on revocation are the highest-value integration: an email or database notification ("A device was signed out from /") turns the feature from a self-service button into an intrusion-detection signal. Hook the package's event (or a model observer on the mapping table) and dispatch a queued notification. Keep the listener queued — the revocation itself should stay synchronous and inside the transaction.

Customize the device list without forking the page. Extend the package's page class and override the table/query, or publish the views if the package supports it. Typical customizations: resolving device names from a user agent parser, masking IPs for GDPR, adding a "last seen" column, hiding devices older than N days.

Multi-panel and multi-guard setups. Register the plugin per panel and confirm the config's model/guard settings match the panel's guard. A common mistake is enabling the page on an admin panel where the User model differs from the one the device rows reference — you'll get an empty or foreign-scoped list.

Test it with real session rows. In feature tests, use the database session driver and create multiple sessions for the same user ($this->actingAs($user) in separate test requests, or insert sessions rows directly), then assert that after revocation the row count drops and a request with the revoked session id is unauthenticated. Asserting only that the device row disappeared is what let the original gap ship.

Gotchas and Tips

  • The session driver matters more than anything else in this package. v0.7.1's fix deletes "real Laravel session rows". That only exists if you use the database session driver. On cookie, file, redis, or array, revocation cannot reach into the driver and the compromised session may survive. If you're on a non-database driver, either switch, or accept that "This isn't me" is a UI-level signal only — and document that for your team.
  • No schema changes in 0.7.1, so the upgrade is a pure composer update. But verify your sessions table has an index on user_id (Laravel's session:table stub includes it) — the new deletion path queries by user, and a missing index turns revocation into a table scan on busy apps.
  • 403 at the service boundary can break existing integrations. If you already call the revocation service from a custom UI (or a queued job where the "current session" is ambiguous), audit those call sites after upgrading. The guard is correct, but it's a behavior change, not a bug.
  • Don't fire the revocation inside a DB transaction you manage. The service opens its own transaction (session deletion + identity/trust changes). Nesting is fine in Laravel, but wrapping it in a long outer transaction that also does slow work (mail, HTTP calls) will hold locks on the sessions table. Let the service own the boundary.
  • trusted_at being cleared is a side effect with a UX cost. Users who marked a device "trusted" (skipping 2FA) will be challenged again after a revocation. That's intended, but expect support tickets; surface it in the confirmation copy.
  • Debugging a "still logged in" report: check sessions for the user in the DB before and after the revoke click. If the device row vanishes but the session row survives, you're either on a non-database driver, calling an old code path, or the mapping row pointed at a session id that no longer matches the live session (which can happen if the mapping is written once at login and Laravel regenerated the id).
  • The reused sign-out path is your extension point. Because revocation funnels through the existing sign-out logic, anything you've customized there (audit logging, remember-token invalidation) applies to revocation too. That's usually desirable — and a good place to add logging rather than patching the package.
  • Upgrade discipline: pin the package version in composer.json and read release notes before bumping. This release is a security fix on a self-service action; older versions silently leave live sessions behind, so treat any pre-0.7.1 install as a known vulnerability rather than a cosmetic bug.
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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
adachsoft/php-code-style