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

Laravel Session Management Laravel Package

jeffersongoncalves/laravel-session-management

Laravel Session Management lets you track and manage active user sessions stored in the database, so users can review logged-in devices and revoke or log out other sessions. Lightweight package for secure session control.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a thin, opinionated layer over Laravel's database session driver: it gives you an Eloquent model for the sessions table, safe payload inspection, and a small service for kicking people out. Everything hinges on one prerequisite, so verify it before anything else.

  1. Confirm you're on the database driver. SESSION_DRIVER=database in .env, and config/session.php has 'driver' => 'database'. If you're on file, redis, or cookie, there is nothing in the sessions table and this package has no data to work with. This is the single most common reason "it doesn't work."
  2. Confirm the table exists. Laravel 11+ ships the sessions migration in the default 0001_01_01_000000_create_users_table.php. Older apps or apps that never switched drivers need php artisan session:table && php artisan migrate. The package follows session.table and session.connection, so a custom table name or a dedicated sessions connection (common in multi-tenant setups) is picked up automatically.
  3. Skim the scopes first. active(), expired(), guests(), authenticated(), forUser() map directly onto the two columns that matter — last_activity and user_id. Almost every feature you'll build is a composition of those plus decodePayload().

First use case — an "active sessions" list on a user profile page. This is the fastest way to validate the install end to end, because it exercises the model, the user() relation, and the scopes together:

use Package\SessionManagement\Models\Session; // namespace per the package README

$sessions = Session::query()
    ->forUser($user)
    ->active()
    ->orderByDesc('last_activity')
    ->get();

foreach ($sessions as $session) {
    $session->ip_address;
    $session->user_agent;
    $session->last_activity;   // unix timestamp
    $session->decodePayload(); // masked array
}

If that returns the row you're currently browsing with, you're wired up correctly. Then try SessionManagement::revoke($session) on a second browser and watch that browser get logged out on its next request.

Implementation Patterns

"Log out other devices" for the current user. The canonical feature. Resolve the current session id from the request session and revoke the rest:

SessionManagement::revokeUser($user, except: $request->session()->getId());

Whether the except parameter is named that way or takes a session id in a different position, check the signature — but the pattern of "revoke all sessions for this user except mine" is the one you want. Wrap it with a password confirmation and, ideally, Auth::logoutOtherDevices($password) so the password_hash_* marker in remaining sessions is also rotated.

Admin-side session visibility. Session::authenticated() for logged-in rows, Session::guests() for anonymous traffic — the latter is surprisingly useful (bot traffic, abandoned carts, "who is hammering this endpoint" debugging). Paginate aggressively; this table gets large on busy apps. Eager-load with('user') when rendering a list, otherwise you'll N+1 across every row.

Incident response / forced logout. On password change, role change, or a suspected compromise, revokeUser($user) is the one-liner. Pair it with a password reset and remember-token rotation (see Gotchas). For a single suspicious session, revoke($session) or revoke($sessionId).

Payload inspection for support tickets. decodePayload() is the reason this package exists over hand-rolled unserialize(). You get the session's key/value array without instantiating any classes, and _token plus password_hash_* are masked by default — safe to render in an admin panel or paste into a ticket:

$session->decodePayload(); // ['_token' => '***', 'password_hash_web' => '***', ...]

Prefer the default. If you genuinely need the real CSRF token (e.g. debugging a token mismatch), the masking is a default rather than a hard rule — pass the flag to disable it, and never log the unmasked output.

Scheduled pruning instead of relying on the lottery. Laravel's own session GC is probabilistic (lottery: [2, 100]), so on low-traffic apps expired rows linger for a long time. Replace or supplement it with a deterministic schedule:

// routes/console.php or bootstrap/app.php
Schedule::command('session-management:prune')->hourly();

prune() only touches expired() rows (older than session.lifetime minutes). It will not log out an active user — that's revokeUser(). Keep that distinction clear in your head and in your code comments.

Testing. Set SESSION_DRIVER=database in phpunit.xml, use RefreshDatabase, and assert on row counts rather than payload contents. A factory-less test like Session::factory-style inserts are usually easiest done by hitting a real login route, which also proves the user() relation resolves against your actual provider.

Gotchas and Tips

  • Revoking a session ≠ logging the user out permanently. If the user ticked "remember me", the remember cookie will silently re-authenticate them and create a new session row. For a real forced logout, also rotate the user's remember_token ($user->forceFill(['remember_token' => Str::random(60)])->save()) or call Auth::logoutOtherDevices().
  • user() is a plain belongsTo via your auth provider. It works for the standard users table with an integer/ULID key. Custom guards, a separate admin table, or polymorphic actors won't resolve — in that case query on user_id yourself and join manually.
  • Encrypted payloads depend on APP_KEY. With session.encrypt on, old rows become undecodable after a key rotation. Expect decodePayload() to fail or return partial data for pre-rotation sessions; don't treat that as a bug. Same story for session.serialization => 'json' — the package handles both, but rows written under a previous setting won't match the current one.
  • "Objects are never instantiated" means incomplete data, not perfect data. Complex values come back as inert structures rather than the original objects. Fine for debugging and auditing; don't build business logic on the decoded payload's nested objects.
  • last_activity is a raw unix timestamp. Don't ->diffForHumans() it directly expecting a Carbon instance; wrap with Carbon::createFromTimestamp(). And active()/expired() hinge on session.lifetime, so a config change shifts the boundary retroactively for every row.
  • Indexing. Add indexes on last_activity and user_id if you don't have them — forUser()->active() and the prune command both scan on those. On a million-row sessions table an unindexed prune is a table scan under a scheduled task.
  • Deleting your own row. An admin revoking "all sessions" from inside an admin panel can nuke their own row and get bounced to the login screen mid-action. Always exclude the current session id in bulk operations.
  • Extension points. The model is a normal Eloquent model — scope it, add accessors (is_current_device, parsed UA), or wrap it in a repository. For anything the service doesn't cover (bulk revoke by IP, revoke by device fingerprint), drop down to the model rather than asking for new API.
  • Debugging checklist when a revoke "doesn't work": (1) driver is database, (2) session.connection points where you think it does, (3) the user's browser didn't have a remember cookie, (4) no AuthenticateSession middleware re-establishing things in an unexpected order.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
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