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

Browser Sessions Laravel Package

cjmellor/browser-sessions

Track and manage user browser sessions in Laravel. See devices, browsers, IP addresses, and last activity, then log out other sessions with a ready-made Blade/Livewire component built on Laravel's database session driver.

View on GitHub
Deep Wiki
Context7

Getting Started

browser-sessions gives you a Jetstream-style "active browser sessions" list without pulling in Jetstream. It reads the rows Laravel already writes to the sessions table, groups them by the logged-in user, and parses the user_agent string into human-readable browser/platform/device labels.

Before installing, confirm the prerequisite that trips most people up: your app must use the database session driver. The package queries the sessions table — with file, redis, or cookie drivers there is nothing to read and you'll get an empty collection forever.

composer require cjmellor/browser-sessions
php artisan vendor:publish   # pick the browser-sessions tag if one is listed

Version constraint for v2.0.0: this is a breaking major purely on framework support — Laravel 13 added, Laravel 10 and 11 dropped. If you're on Laravel 10/11 you must stay on ^1.3; pin accordingly. On Laravel 12/13 the upgrade from 1.3.2 is a composer update with no code changes expected (the rest of the diff is Dependabot CI pins).

First use case — the profile page. In a controller:

use Cjmellor\BrowserSessions\Facades\BrowserSessions;

public function edit()
{
    return view('profile.sessions', [
        'sessions' => BrowserSessions::sessions(),
    ]);
}

Then dd(BrowserSessions::sessions()->first()) once in tinker to see exactly which accessors this version exposes (browser(), platform(), device(), isCurrentDevice(), lastActive(), ip_address, last_activity) before writing Blade — the object shape is the one thing worth verifying rather than assuming.

Implementation Patterns

Read + revoke in one screen. The canonical workflow is a table of sessions where the current one is labelled "This device" and every other row has a "Log out" button. Pair the list with the revoke call:

BrowserSessions::logoutOtherBrowserSessions($request->input('password'));

This is the same behaviour as Jetstream's LogoutOtherBrowserSessions action: it re-validates the password, then deletes every session row for that user except the current session ID. Put it behind a password.confirm-style form request and a POST route — never a GET.

Wrap it in your own service, don't scatter the facade. A thin ActiveSessions class that returns a typed collection is worth the ten minutes: it gives you one place to filter out stale rows, one place to change if the package's API shifts, and something you can fake in tests instead of hitting the sessions table.

Blade component, not a page. Ship it as <x-active-sessions /> so the same markup works on a Breeze profile page, a Filament/Livewire settings panel, or a Fortify profile.show view. In Livewire, call BrowserSessions::sessions() inside render() or a computed property rather than caching it in a public property — the data is cheap to read and goes stale instantly.

Multi-guard apps. The package keys off the session row's user_id. If you have admins and users sharing one session table, scope the output yourself (filter the returned collection on your guard's user ID) rather than trusting the default filtering.

Testing. BrowserSessions::logoutOtherBrowserSessions() is easy to assert on: create two session rows with Session::getId()-style IDs, call the action, assert only the current one remains. For feature tests use actingAs($user) plus withSession(); the framework's DatabaseSessionHandler writes the row you need during the request lifecycle.

Gotchas and Tips

The upgrade is a constraint change, not a feature release. v2.0.0 carries no new public API. Don't schedule a "v2 migration" sprint — update composer.json, run the suite, done. The trap is transitive: orchestra/testbench and PHP version bounds move with the Laravel requirement, so CI matrices on PHP 8.1 will break before your app code does.

Session pruning silently empties the list. Laravel's lottery on the session garbage collector deletes rows older than session.lifetime. If you set lifetime to 120 minutes, "active sessions" legitimately shows very little and users will report it as a bug. Either raise the lifetime or accept it — but document the number next to the UI.

Detecting "this device" is fuzzy. The current session is identified by Session::getId(). Behind a load balancer or with a session regenerated on login, the match can fail and the UI offers to log out the very device you're on. Test the flow end-to-end after login, especially with session.driver=database plus a remember-me cookie.

IP addresses will be wrong behind a proxy unless TrustProxies includes your LB. Same ip_address on every row is almost always this, not a package bug.

Don't hand-roll password verification. logoutOtherBrowserSessions($password) expects the plaintext password and does the Hash::check internally against the authenticated user. Passing a hash, or a user model from a non-default guard, produces a confusing failure — validate and fail loudly at the form request layer first.

Keep a ^1.3 pin handy in composer.json history for any package or satellite app still on Laravel 11; a monorepo with mixed framework versions cannot share one lockfile for this dependency.

Debug with the table, not the facade. When the list is empty, run select user_id, count(*) from sessions group by user_id — it tells you in five seconds whether this is a driver/config problem (no rows, null user_id) or a presentation problem (rows exist, parsing failed).

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource