dorfteich/docs/architecture/adr/0007-auth-sessions-oidc-ready.md
Claude Fable 5 0629411966 Add architecture documentation, ADRs, and operations concept
Initial deliverable of the architecture phase: 16 ADRs (stack, CRDT
collaboration, plugin sandbox, import/export, backups, CI/CD), data
model, permission model, real-time collaboration and plugin concepts,
deployment/operations/security documentation, and the milestone roadmap
that the implementation issues are derived from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 14:36:16 +02:00

2.7 KiB

ADR 0007: Cookie sessions, Argon2id, OIDC-ready identity model

  • Status: accepted
  • Date: 2026-07-04

Context

Kickoff decisions: self-contained user management (username, e-mail, password) with mandatory e-mail verification (double opt-in), password reset, rate limiting, and the option to disable self-registration per instance. SSO is not in the MVP but the design must allow adding OIDC login later without schema surgery.

Decision

Authentication

  • Server-side sessions stored in PostgreSQL, referenced by an opaque HttpOnly; Secure; SameSite=Lax cookie. No JWTs for browser sessions (revocability and simplicity win). Sliding expiration, default 30 days.
  • Passwords hashed with Argon2id (tuned parameters documented in code).
  • E-mail flows (verification, password reset) use single-use, expiring, hashed tokens; mail is sent via SMTP (instance-configured, see setup wizard) through a mail outbox table with retry.
  • Rate limiting on signup, login, password reset, and token endpoints: fixed-window counters in PostgreSQL keyed by IP and by account — no Redis (ADR 0002).
  • Self-registration can be disabled instance-wide (instance_settings.registration_mode: open | closed). The kickoff also asked for the option of admin approval as a later hardening step; the setting is an enum so approval_required can be added without migration pain.
  • Collaboration tokens: the API issues short-lived (≤ 60 s validity for connect) signed JWTs solely for the WebSocket handshake with the collab server (ADR 0003). These are the only JWTs in the system.

OIDC readiness (not in MVP)

  • The identity model separates account from login method: users (profile, status) and user_identities (provider = password | future oidc:<issuer>, subject, credential). Password login is just one identity row.
  • E-mail is unique per user and verified; future OIDC linking matches on verified e-mail or explicit account linking.

Consequences

  • Logout and account deactivation are immediate (session rows deleted).
  • No shared secret sprawl: one signing key for collab tokens, rotated via environment configuration.
  • Adding OIDC later means: new identity provider rows, an authorization-code flow module, and a login button — no changes to sessions, permissions, or user references.

Alternatives considered

  • JWT access/refresh tokens in the browser: harder revocation, XSS exposure of tokens, no benefit for a same-origin SPA. Rejected.
  • Auth libraries/services (Keycloak, Authentik as mandatory): heavy extra container contradicting easy self-hosting; external IdPs remain possible later through the OIDC path.