Sessions#
Keywords: session store, session cookie, cookie expiration, file session, memory session, session lifespan, session lifetime
Server-side sessions with signed cookie IDs.
Usage#
from asok import Request
def render(request: Request):
# Read
username = request.session.get("username")
# Write
request.session["username"] = "alice"
request.session["cart"] = [1, 2, 3]
return request.html("page.html")
Sessions are lazy-loaded on first access. Modified sessions are automatically saved when the response is sent.
SESSION_MAX_AGE controls the browser cookie lifetime, while SESSION_TTL controls how long the server keeps session data before expiring it.
Configuration#
| Key | Default | Description |
|---|---|---|
SESSION_BACKEND | "memory" | "memory", "file", or "redis" |
SESSION_PATH | ".sessions" | Directory for file backend |
SESSION_MAX_AGE | 2592000 | Browser cookie lifetime in seconds |
SESSION_TTL | 86400 | Session lifetime in seconds |
REDIS_URL | None | Redis connection URL (e.g. redis://localhost:6379/0) |
Cookie Security#
SameSite attribute#
Asok uses two types of session cookies with different security policies:
-
Primary session cookie (
asok_sid): UsesSameSite=Strictfor maximum CSRF protection. This is the main session identifier used by the framework. -
Public session cookie (
asok_session): UsesSameSite=Laxby default, which is appropriate for public-facing applications where users may arrive via external links (email, social media, etc.).
The Lax policy allows the cookie to be sent on top-level navigations (e.g., clicking a link from another site), while still preventing it from being sent in most cross-site scenarios. This provides a good balance between security and usability for public applications.
Configure SameSite policy#
You can override the default Lax policy if needed:
# In wsgi.py
app.config["SESSION_SAMESITE"] = "Strict" # or "Lax" (default) or "None"
Or via .env:
SESSION_SAMESITE=Strict
Note: Using
SameSite=Strictprovides stronger CSRF protection but may break user experience in scenarios where users arrive from external links (they will need to login again).SameSite=Lax(default) is the recommended setting for most public-facing applications.Warning: Setting
SameSite=Nonerequires theSecureflag (HTTPS only) and should only be used in specific cross-site scenarios (e.g., embedded iframes).
Session Lifetime (TTL)#
The SESSION_TTL configuration controls how long session data persists on the server before expiring. The default value is 86400 seconds (24 hours).
Production Security Recommendations#
For security-sensitive applications (financial, healthcare, admin panels), reduce the session lifetime to 1-2 hours to minimize the window of opportunity for session hijacking attacks:
# .env - Recommended for sensitive applications
SESSION_TTL=3600 # 1 hour
# or
SESSION_TTL=7200 # 2 hours
Or in wsgi.py:
app.config["SESSION_TTL"] = 3600 # 1 hour
Guidelines by Application Type#
| Application Type | Recommended TTL | Reasoning |
|---|---|---|
| Public websites | 86400s (24h) | Default - Good balance between UX and security |
| E-commerce | 7200s (2h) | Moderate security, prevents abandoned cart session reuse |
| Banking/Finance | 1800-3600s (30min-1h) | High security, short exposure window |
| Admin panels | 3600s (1h) | High security, administrative privileges require shorter sessions |
| Healthcare (HIPAA) | 900-1800s (15-30min) | Compliance requirement, PHI protection |
Note:
SESSION_TTLdiffers fromSESSION_MAX_AGE: -SESSION_TTL: Server-side session data lifetime (how long data is stored) -SESSION_MAX_AGE: Client-side cookie lifetime (how long browser keeps the cookie)For maximum security, set both to the same value. For better UX, you can set
SESSION_MAX_AGElonger and implement "remember me" functionality separately.
Auto-expiration#
Sessions automatically expire after SESSION_TTL seconds of inactivity. The timer resets on each request that modifies the session. Expired sessions are: - Removed from memory backend automatically - Cleaned up from file backend on next access attempt - Cleaned up natively and automatically by Redis (when using the redis backend, which uses native Redis key expiration)
Production Tip: For file-based sessions, implement a cron job to periodically clean up expired session files:
# Cleanup sessions older than SESSION_TTL
find /run/asok/sessions -type f -mtime +1 -delete
File backend#
app.config["SESSION_BACKEND"] = "file"
app.config["SESSION_PATH"] = ".sessions"
Sessions are stored as JSON files in the specified directory.
How it works#
- A signed cookie (
asok_sid) identifies the session - Session data is stored server-side (memory or file)
- On first
request.sessionaccess, data is loaded from the store - If
session.modifiedisTrueat response time, data is saved back
Session API#
request.session behaves like a regular dict:
request.session["key"] = "value"
request.session.get("key", "default")
del request.session["key"]
request.session.pop("key")
request.session.clear()
All mutating operations automatically set session.modified = True.
Production Persistence#
In production environments using multi-worker servers like Gunicorn, you must use either the
fileor theredisbackend.The default
memorybackend stores sessions in the RAM of the specific worker process. Since requests are distributed across multiple workers, a user will "lose" their session as soon as their request is handled by a different worker.
Option A: Redis backend (Recommended)#
Redis stores sessions in-memory, sharing them instantly across all worker processes and even multiple servers, while remaining extremely fast.
To use Redis, install the optional extra:
pip install "asok[redis]"
Configure your .env file:
SESSION_BACKEND=redis
REDIS_URL=redis://localhost:6379/0
Option B: File backend#
To ensure persistence across workers using files, configure the file backend in your .env or wsgi.py:
# .env
SESSION_BACKEND=file
SESSION_PATH=/run/asok/sessions
Note: If you are using SystemD
RuntimeDirectory=asok, the path/run/asokis automatically managed and has the correct permissions for the web server user.
Adjust SESSION_MAX_AGE and SESSION_TTL separately if you want the cookie lifetime and server-side lifetime to differ.
For RHEL/AlmaLinux servers, see the Deployment guide for handling SELinux permissions.
Was this page helpful?