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 Inactivity Guard Laravel Package

eightcedars/filament-inactivity-guard

Filament Inactivity Guard adds configurable idle-session protection to Filament panels, automatically logging users out after inactivity to secure unattended admin areas. Easy to install and configure for Laravel and Filament apps.

Deep Wiki
Context7

Getting Started

Install and register

composer require eightcedars/filament-inactivity-guard
php artisan vendor:publish --tag="filament-inactivity-guard-config"

Register the plugin on the panel(s) you want protected — typically in app/Providers/Filament/AdminPanelProvider.php:

use Eightcedars\FilamentInactivityGuard\FilamentInactivityGuardPlugin;

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

Where to look first

  1. config/filament-inactivity-guard.php — this is the contract you'll actually live with. Read it before writing any code: it controls the idle timeout, warning lead time, redirect target, and which guards/panels are covered.
  2. The plugin's service provider — to confirm which middleware it pushes onto the panel and whether it registers a Livewire hook or a JS timer.
  3. Your config/session.php — see the Gotchas section; these two files must agree.

First use case

The 80% case is: an admin leaves a tab open over lunch, the session expires, and they come back to a half-filled form and a 419 Page Expired. The minimal win is to set a 15-minute idle timeout with a 60-second warning modal, and redirect to filament.admin.auth.login on expiry. That's a three-line config change plus plugin registration — you can ship it in a single PR and it immediately stops the "my form submission was lost" support tickets.

Verify it works by setting the timeout to 1 minute locally, opening a panel page, and walking away. If nothing happens, your issue is almost always config caching or a session driver mismatch, not the plugin.

Implementation Patterns

Panel-scoped rollout. Don't enable it globally on day one. Register the plugin only on the admin panel first, run it for a week, then extend to customer-facing panels where a surprise logout is more disruptive. Filament panel providers make this trivial — each panel is an isolated registration point.

Tiered timeouts per panel. Admin panels can be aggressive (10–15 min). A support-desk panel where agents are reading long tickets wants 30+ minutes. Keep the timeout in config/ but override per-panel via the plugin's fluent setters if available, or via a small config key per panel id. This avoids the classic mistake of picking one number for every surface.

Pair the warning with a "stay signed in" ping. The warning modal's value is only realized if acknowledging it resets the idle clock. Confirm the plugin's keep-alive action touches the session (a Livewire request that hits the session middleware is enough) — otherwise the user clicks "I'm here" and gets logged out 30 seconds later. If the package doesn't ship this, add a tiny Livewire component that calls session()->regenerate() or simply reloads the current page.

Preserve intent across the logout. When redirecting to login, append the current URL as a redirect / intended query param so the user lands back where they were. Filament's auth flow honors url.intended from the session, so set it in a logout listener rather than hand-building the URL:

Event::listen(\Illuminate\Auth\Events\Logout::class, function ($event) {
    if ($event->guard === 'web') {
        session()->put('url.intended', url()->previous());
    }
});

Multi-guard awareness. If your app has web and a separate admin guard, decide explicitly which guards the plugin touches. Logging out the wrong guard leaves an admin authenticated while their panel page reloads into a "logged out" state — confusing and occasionally a security hole.

Test with time travel, not sleep(). The only sane way to test this is:

$this->actingAs($admin);
$this->get('/admin');
Carbon::setTestNow(now()->addMinutes(16));
Livewire::test(SomePage::class)->assertRedirect(route('filament.admin.auth.login'));

Put a Pest helper around this so every panel has one regression test. If the plugin uses a JS timer rather than a server-side check, you'll need Dusk or a headless browser — budget for that early, because it changes your CI story.

Layer it with an existing auth.session middleware. If you already have Laravel's AuthenticateSession enabled, keep it. This plugin governs the Filament UX; AuthenticateSession governs password-change invalidation. They solve different problems and don't conflict.

Config-driven timeouts in .env. Bind the timeout to an env var (INACTIVITY_GUARD_TIMEOUT=15) rather than hardcoding in the config file. Ops will want to tighten it after an incident without a deploy, and it makes per-environment tuning (short in staging to exercise the flow) painless.

Gotchas and Tips

SESSION_LIFETIME must be ≥ your idle timeout. This is the #1 source of "the guard doesn't work" reports. If your session lifetime is 120 minutes and your guard timeout is 15, the guard fires — but if you set the guard to 15 and the session to 10, PHP silently destroys the session first and the user gets a raw 419 with no warning modal. Set SESSION_LIFETIME comfortably above the guard's timeout + warning window.

Config caching will bite you. After any change to config/filament-inactivity-guard.php, run php artisan config:clear locally and redeploy with config:cache in production. Env-var reads inside the config file only work while uncached — a classic "works locally, wrong in prod" trap.

Livewire polling does not count as activity — or does it? Depends entirely on how the plugin measures idleness. If it hooks the session's last_activity timestamp, any Livewire poll (notifications, table refreshes) resets the clock and your idle timeout never fires for users with a dashboard open. If it uses its own client-side timer, polling is ignored. Determine which model this package uses before promising anyone "15 minutes means 15 minutes." If it's session-based and you need true idle detection, you'll have to exclude polling requests or track activity client-side.

Multiple tabs desync silently. Tab A shows the warning modal; Tab B is idle. Acknowledging in tab A doesn't tell tab B anything unless the plugin uses BroadcastChannel or localStorage events. If you care, listen for storage events yourself and dismiss/reload accordingly. For most apps this is cosmetic, but in a kiosk or shared-workstation deployment it matters.

"Remember me" users are not exempt by default. A user who checked "remember me" still has a session; if the guard logs them out, Laravel's remember cookie may silently re-authenticate them on the next request, making the logout appear to fail. Test this path explicitly, and decide whether the plugin should also invalidate the remember token ($user->setRememberToken(null)). Most teams want the remember token kept — the point is protecting an unattended screen, not revoking the device.

Redirect target must be a named route that exists in that panel. filament.admin.auth.login only resolves if the admin panel has auth enabled and the panel id matches. A copy-pasted config across panels is a five-minute debugging session you don't need. Log the resolved route name once during setup.

Don't forget the logout event listener. Anything you do on logout (audit logging, releasing locks, clearing draft state) fires from Illuminate\Auth\Events\Logout. If the plugin bypasses Laravel's normal logout and calls Auth::logout() directly, that's fine — the event still fires. But if it just invalidates the session without logging out the guard, no event fires and your audit trail has a hole. Read the package's logout path and confirm.

Extension points to know. Look for: a publishable Blade view for the warning modal (so you can restyle it to your brand), a shouldRegister() / isEnabled() hook for conditional activation, and any events the plugin dispatches. The Blade view override is the one you'll actually use — the default modal looks like a Filament default, which is fine, but the copy ("You'll be logged out in…") usually needs rewriting for non-technical users.

Version pin, then verify. Stars are modest (25) and the last release is dated 2026-02-16, so the package is maintained but not battle-tested at scale. Pin a minor version in composer.json, read the changelog before every bump, and keep your own regression test around the idle flow so an upstream change can't silently disable your logout policy. For a security-adjacent feature, your test — not the package's — is the source of truth.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource