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

Sesshin Laravel Package

sobstel/sesshin

Sesshin provides encrypted, authenticated session storage for PHP. It transparently encrypts session data with libsodium or OpenSSL, keeping contents unreadable in files, Redis, or databases while staying compatible with PHP's native session handling.

Deep Wiki
Context7

Getting Started

Sesshin is a framework-agnostic, security-focused replacement for native PHP sessions. It wraps the pieces you usually hand-roll (ID generation, cookie handling, fingerprinting, encryption) into composable objects. It is not a Laravel package, so day-to-day use means wiring it into your own bootstrap or a small service provider.

1. Install

composer require sobstel/sesshin

2. Where to look first

  • src/Sesshin/Session.php — the façade everything else plugs into.
  • src/Sesshin/Store/ — where session data lives (Native, Memory).
  • src/Sesshin/Id/Generator/ and src/Sesshin/Id/Handler/ — how IDs are created and transported.
  • src/Sesshin/Fingerprint/ — hijack detection (checkers + storage).
  • src/Sesshin/Crypt/ — encryption at rest.

Read Session.php plus one implementation of each interface before anything else; the rest of the library is small.

3. Minimal bootstrap

use Sesshin\Session;
use Sesshin\Store\Native;
use Sesshin\Id\Generator\Random;
use Sesshin\Id\Handler\Cookie;

$session = new Session(
    new Native(),
    new Random(),      // CSPRNG-backed id generator
    new Cookie([       // id transport
        'path'     => '/',
        'httponly' => true,
        'secure'   => true,
        'samesite' => 'Lax',
    ])
);

$session->start();

4. First use case: login state

// login.php
$session->regenerateId();          // kill session-fixation from pre-auth
$session->set('user_id', $user->id);
$session->set('logged_in_at', time());

// later requests
if ($session->get('user_id') === null) {
    // unauthenticated
}

That’s the 80% path: encrypted, regenerated-on-login session state with a hardened cookie. Add fingerprinting and encryption in the next step.

Implementation Patterns

Wrap it in one app-level service. Don’t scatter new Sesshin\Session(...) across controllers. Build a single configured instance (or a container singleton) so cookie options, fingerprint rules, and the crypt key are defined in one place.

final class AppSession
{
    private Session $session;

    public function __construct(array $config)
    {
        $this->session = new Session(
            new Native(),
            new Random(),
            new Cookie($config['cookie'])
        );
        $this->session->setFingerprint(new Fingerprint([
            new UserAgent(),
            new Ip(),   // configure trusted proxies if behind a load balancer
        ]));
        $this->session->setCrypt(new OpenSSL($config['key']));
        $this->session->start();
    }

    public function get(string $k, $default = null) { return $this->session->get($k, $default); }
    public function set(string $k, $v): void { $this->session->set($k, $v); }
    public function regenerate(): void { $this->session->regenerateId(); }
    public function destroy(): void { $this->session->destroy(); }
}

Auth flow pattern. Regenerate on privilege change only — login, logout, password change, role escalation. Regenerating on every request breaks concurrent tabs and mobile clients.

// on successful login
$session->regenerateId();
$session->set('auth', ['id' => $user->id, 'role' => $user->role]);

// on logout
$session->destroy();

Namespaced keys instead of nested blobs. Sesshin’s accessor API is flat (get/set/has/remove). Prefer explicit prefixes (auth.user_id, cart.items, flash.success) over stuffing arrays into one key — it makes clearing one concern and grepping logs easier.

Flash messages are just a convention on top of the store:

$session->set('flash.success', 'Saved.');
// next request, after rendering:
$session->remove('flash.success');

Encryption for sensitive payloads only. Encryption adds CPU and key-management overhead. Use setCrypt() when the store is disk/DB-backed and holds PII or tokens; skip it if the store is already an encrypted at-rest backend (e.g., Redis with TLS + disk encryption) and the cookie is secure + httponly. Rotate keys by decrypting with the old key, re-encrypting, and invalidating sessions.

Testing with the memory store. Swap Native for Sesshin\Store\Memory in unit tests; no headers, no session_start, deterministic.

$session = new Session(new Memory(), new Random(), new Cookie());
$session->start();

Framework integration. There is no first-party Laravel/Symfony bridge; treat it as a library, not a driver. In Laravel, instantiate it in a singleton service provider and keep it out of Laravel’s own session middleware lifecycle — do not try to make it a SessionHandlerInterface under the existing driver unless you are prepared to disable Laravel’s session middleware. In legacy or Slim projects, resolve it at the front controller, before any output.

Gotchas and Tips

  • Maintenance risk. Last release was 2018 and stars are modest. Pin the version, run it through your own security review, and be ready to vendor a fork. Test on every PHP minor upgrade — expect issues on PHP 8.x where mcrypt was removed; use the OpenSSL crypt implementation, not the legacy one.
  • Headers must not be sent yet. The cookie handler writes the session cookie, so start() has to run before any output. In CLI this is irrelevant, but a stray echo or ?> at the top of a bootstrap file will silently break session persistence.
  • Never double-start. If you also call session_start() (or Laravel’s session middleware runs), the native store will conflict and you may lose or corrupt state. Pick one owner of the session lifecycle per request.
  • Fingerprint false positives. Hashing the full User-Agent or raw IP will log out legitimate users on browser updates, mobile network switches, and proxy IP rotation. Either relax the checker (UA family, not exact string) or configure trusted proxies so IP resolution is stable.
  • Key handling. Don’t commit the crypt key. Load it from env/secrets manager. A missing or empty key should fail loudly, not silently fall back to plaintext.
  • ID regeneration races. regenerateId() deletes the old record; concurrent in-flight requests holding the old ID will appear logged out. Do it on login/logout only, not per-request.
  • No session locking. Concurrent requests can read-modify-write the same session and clobber each other. For anything transactional, keep the critical section small or use a store that provides locking.
  • Debugging checklist: log the incoming session cookie, log whether the fingerprint check passed, log whether the crypt layer threw. Most “random logouts” are one of: cookie not set (secure over HTTP), fingerprint mismatch, or old ID after regeneration.
  • Extension points are clean. Subclass or implement:
    • Store for Redis/DB-backed storage,
    • Checker for custom fingerprint dimensions (e.g., bind to an org/tenant ID, not to client IP),
    • Generator for ID format policies,
    • Handler for non-cookie transport (rare). Keep custom checkers additive; removing one later invalidates every existing session and forces re-authentication.
  • Don’t mix with $_SESSION. Treat the Sesshin store as the source of truth. Reading/writing $_SESSION directly alongside it is the fastest way to produce state you can’t explain during an incident.
  • Document the session contract. Because Sesshin has no framework conventions (no Auth::user(), no CSRF helper), your AppSession wrapper is where you define lifetime, cookie attributes, fingerprint rules, and logout semantics. That class is the thing you actually maintain.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings