Skip to content

003 — Simple session auth (httpOnly cookies)

Context

Multiple users must sign in and manage their own domains so claims and ownership can be exercised. Teams, SSO, OAuth, and RBAC would dominate the challenge without teaching the domain model. The SPA and Worker share a first-party (or proxied) origin relationship, so cookie auth is practical.

Decision

Email + password (PBKDF2), httpOnly session cookie (not readable by JS), server-side sessions rows with expiry, and a users table. No orgs, invites, or SSO.

Cookies over bearer tokens in localStorage / sessionStorage because:

  • XSS cannot exfiltrate an httpOnly cookie the way it can a token sitting in web storage.
  • The browser sends the cookie automatically with credentials: 'include'; no custom Authorization header on every tRPC call.
  • Logout / expiry is a server-side row delete plus Set-Cookie clear — client JS cannot “keep” a bearer token after logout as easily.
  • The prototype stays same-site / first-party; there are no mobile native clients that usually prefer bearer tokens.

Consequences

  • Auth surface stays small (auth.* procedures); session expiry and delete-on-lookup are enough.
  • CSRF is a lesser concern for same-site cookies + tRPC mutations from the SPA origin; harden further if the cookie ever becomes cross-site.
  • Replacing with a real IdP later should not require changing domain ownership rules.
  • A public API or native app would likely add bearer/OAuth later — out of scope here.