NAME
Trickster::Session - Stateless signed-cookie sessions for Trickster
SYNOPSIS
use Trickster::Session;
use Trickster::Cookie;
my $cookie = Trickster::Cookie->new(
secret => $ENV{SESSION_SECRET} || die "SESSION_SECRET required",
);
my $session = Trickster::Session->new(
cookie => $cookie,
name => 'trick_session',
max_age => 3600,
secure => 1,
httponly => 1,
samesite => 'Lax',
);
# In your routes
$app->get('/login', sub {
my ($req, $res) = @_;
# Authenticate user...
$session->set($res, {
user_id => 123,
username => 'alice',
role => 'admin',
});
return $res->json({ success => 1 });
});
$app->get('/profile', sub {
my ($req, $res) = @_;
my $data = $session->get($req);
my $user_id = $data->{user_id};
unless ($user_id) {
return $res->json({ error => 'Not authenticated' }, 401);
}
return $res->json({ user_id => $user_id });
});
$app->post('/logout', sub {
my ($req, $res) = @_;
$session->clear($res);
return $res->json({ success => 1 });
});
DESCRIPTION
Trickster::Session provides stateless, signed-cookie based sessions that:
Work in production (prefork servers, load balancers)
Survive server restarts
Scale horizontally without shared storage
Are cryptographically signed (tamper-proof)
Store data client-side (no server memory)
IMPORTANT: This is NOT a middleware. Sessions are stateless and stored in signed cookies. No server-side storage means no memory leaks, no database queries, and perfect horizontal scaling.
WHY NOT MIDDLEWARE?
Traditional session middleware with in-memory storage (like the one we almost shipped) has fatal flaws:
Breaks in prefork servers (Starman, uWSGI, Apache)
Lost on server restart
Doesn't scale horizontally
Memory leaks with many sessions
Stateless signed-cookie sessions solve all these problems.
METHODS
new(%options)
Creates a new session manager.
Required:
cookie - Trickster::Cookie instance with secret
Optional:
name - Cookie name (default: 'trick_session')
max_age - Session lifetime in seconds
secure - Require HTTPS (default: 1)
httponly - HttpOnly flag (default: 1)
samesite - SameSite policy (default: 'Lax')
get($req)
Retrieves session data from the request.
Returns a hash ref (empty if no session).
set($res, $data)
Stores session data in a signed cookie.
$data must be a hash ref that can be JSON-encoded.
clear($res)
Clears the session by deleting the cookie.
SECURITY
All session data is HMAC-signed
Tampering is detected and rejected
Use a strong random secret (32+ bytes)
Rotate secrets periodically
Enable secure flag in production (HTTPS)
LIMITATIONS
Cookie size limit (~4KB)
Session data is visible to client (base64-encoded)
Don't store sensitive data (passwords, credit cards)
Store only user ID and lookup details server-side
BEST PRACTICES
# Good: Store minimal data
$session->set($res, {
user_id => 123,
role => 'admin',
});
# Bad: Store sensitive data
$session->set($res, {
password => 'secret', # NEVER!
credit_card => '...', # NEVER!
});
# Good: Use environment variable for secret
my $cookie = Trickster::Cookie->new(
secret => $ENV{SESSION_SECRET} || die "SESSION_SECRET required",
);
# Bad: Hardcoded secret
my $cookie = Trickster::Cookie->new(
secret => 'my-secret', # NEVER!
);