Skip to content

fix: store sessions in the database and limit them to 24 hours - #1128

Merged
rohan-chaturvedi merged 7 commits into
mainfrom
fix/ph-006-server-side-sessions
Nov 12, 2026
Merged

rohan-chaturvedi merged 7 commits into
mainfrom
fix/ph-006-server-side-sessions

Conversation

@rohan-chaturvedi

@rohan-chaturvedi rohan-chaturvedi commented Nov 10, 2026 •

Copy link
Copy Markdown
Member

🔍 Overview

Moves sessions to Django's database-backed session store and shortens the default session lifetime to 24 hours. Session data is kept server-side and the browser cookie only carries a session key. Signing out removes the session record.

💡 Proposed Changes

  • SESSION_ENGINE is now django.contrib.sessions.backends.db. The django_session table already exists, so there is no migration.
  • A session now ends 24 hours after sign-in (was 7 days). The end is fixed at sign-in: later requests that write to the session do not move it, and neither does the re-login after a password change, account recovery or email change.
  • The new optional SESSION_LIFETIME_HOURS environment variable sets a different whole number of hours. Any other value stops the application from starting, with a clear error. It is documented in .env.example.
  • A daily job removes expired session rows (Django's clearsessions). It is registered on migrate and at worker startup, like the existing sweeps, and runs on the maintenance worker. No new queue or process.
  • Tests keep sessions in the in-memory cache, because the suite runs without a database.
  • Comments that described sessions as signed cookies are updated.

🖼️ Screenshots or Demo

N/A — no UI change.

📝 Release Notes

Sessions are now stored server-side and end 24 hours after sign-in by default. Self-hosted instances can change this with SESSION_LIFETIME_HOURS. Everyone will need to sign in again once after upgrading.

❓ Open Questions

N/A

🧪 Testing

  • New tests: signing out deletes the session record, the session key is not accepted afterwards, and other sessions of the same user are unaffected.
  • New tests for the lifetime: the setting (default, valid and invalid values), the end being fixed at sign-in, a later session write and a re-login not moving it, and a new sign-in starting a new lifetime.
  • New tests for the purge job's registration and its startup hook in the worker.
  • On a local instance: password login, two-step login, sign-out, password change, account recovery and the SSO start all work. A new session's cookie and record both expire after 24 hours, or after 6 hours with SESSION_LIFETIME_HOURS=6. With a simulated clock, a session write at hour 20 and a password change at hour 23 leave the end at hour 24, and the session is not accepted at hour 25. Ordinary requests do not rewrite the session. The purge job removed an expired session on the real worker. A browser that still holds an old cookie is sent to the login page.
  • Full backend test suite passing locally.

🎯 Reviewer Focus

SESSION_ENGINE and session_lifetime_seconds in backend/backend/settings.py, start_session_lifetime in backend/api/signals.py, relogin_preserving_session in backend/api/utils/reauth.py, and backend/api/tasks/sessions.py.

➕ Additional Context

  • Existing sessions end at upgrade. During a rolling or blue-green deploy, requests can land on old and new instances, so users may be asked to sign in again until the switch completes.
  • A user is asked to sign in again 24 hours after sign-in even if they are active.
  • One extra indexed read on django_session per session-authenticated request. API tokens (CLI, SDKs) do not use sessions and are unaffected.
  • Docs for SESSION_LIFETIME_HOURS: docs: document SESSION_LIFETIME_HOURS docs#277.

✨ How to Test the Changes Locally

docker compose -f dev-docker-compose.yml exec backend pytest \
  tests/test_session_logout.py \
  tests/test_session_lifetime.py \
  tests/tasks/test_sessions.py \
  tests/api/test_rqworker_command.py

Then sign in to the console, sign out, and sign in again.

💚 Did You...

  • Ensure linting passes (code style checks)?
  • Update dependencies and lockfiles (if required) — N/A
  • Update migrations (if required) — N/A (the table already exists)
  • Regenerate graphql schema and types (if required) — N/A
  • Verify the app builds locally?
  • Manually test the changes on different browsers/devices? — N/A (no UI change; sign-in and sign-out checked in Chromium)

@rohan-chaturvedi rohan-chaturvedi changed the title fix: store sessions in the database fix: store sessions in the database and limit them to 24 hours Nov 10, 2026
@rohan-chaturvedi
rohan-chaturvedi merged commit 88b9b5a into main Nov 12, 2026
15 checks passed
@rohan-chaturvedi
rohan-chaturvedi deleted the fix/ph-006-server-side-sessions branch November 12, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants