feat: add sliding session timeout with idle and absolute caps
This commit is contained in:
@@ -154,6 +154,7 @@ Copy `.env.example` to `.env` and configure:
|
||||
- `POST /api/v1/auth/logout` - Logout
|
||||
- `GET /api/v1/auth/me` - Get current user
|
||||
- `GET /api/v1/auth/sessions` - Get user sessions
|
||||
- `POST /api/v1/auth/sessions/refresh` - Extend session idle window
|
||||
- `DELETE /api/v1/auth/sessions/:id` - Revoke session
|
||||
|
||||
### Users
|
||||
@@ -264,6 +265,52 @@ gunicorn -w 4 -b 0.0.0.0:8000 wsgi:app
|
||||
- Request ID tracking for audit trails
|
||||
|
||||
|
||||
## Session Management
|
||||
|
||||
Sessions are database-backed bearer tokens stored in PostgreSQL. Each session is created at login and validated on every authenticated request via the `login_required` decorator.
|
||||
|
||||
### Sliding Timeout
|
||||
|
||||
Sessions use a **sliding window** model with two independent limits:
|
||||
|
||||
| Timeout | Default | Env Var | Behaviour |
|
||||
|---------|---------|---------|-----------|
|
||||
| **Idle** | 15 min | `SESSION_IDLE_TIMEOUT` | Extends automatically on every request. If no request is made within this window the session expires. |
|
||||
| **Absolute** | 8 h | `SESSION_ABSOLUTE_TIMEOUT` | Hard cap measured from session creation. Activity cannot extend a session beyond this point. |
|
||||
|
||||
Every authenticated request resets the idle clock by calling `Session.refresh()`, which sets `expires_at = now + idle_timeout` — but never past `created_at + absolute_timeout`. This means:
|
||||
|
||||
- An active user stays logged in indefinitely **up to** the absolute cap.
|
||||
- An idle user is logged out after the idle timeout.
|
||||
- No session can survive longer than the absolute timeout regardless of activity.
|
||||
|
||||
### Configuration
|
||||
|
||||
Override defaults via environment variables:
|
||||
|
||||
```bash
|
||||
SESSION_IDLE_TIMEOUT=900 # seconds (15 min)
|
||||
SESSION_ABSOLUTE_TIMEOUT=28800 # seconds (8 h)
|
||||
```
|
||||
|
||||
### Cleanup
|
||||
|
||||
Expired sessions are soft-marked as `EXPIRED` by the `cleanup_sessions` job. Run it periodically via the job runner:
|
||||
|
||||
```bash
|
||||
python manage.py cleanup_sessions
|
||||
|
||||
# Or via the job runner (Docker):
|
||||
JOB_NAME=cleanup_sessions JOB_INTERVAL_SECONDS=300
|
||||
```
|
||||
|
||||
### Session Endpoints
|
||||
|
||||
- `GET /api/v1/auth/sessions` — List active sessions for the current user
|
||||
- `POST /api/v1/auth/sessions/refresh` — Extend the current session's idle window (returns new `expires_at`)
|
||||
- `DELETE /api/v1/auth/sessions/:id` — Revoke a specific session
|
||||
|
||||
|
||||
# Boostrap db
|
||||
python manage.py db upgrade
|
||||
|
||||
|
||||
Reference in New Issue
Block a user