Skip to content

Latest commit

 

History

History
43 lines (29 loc) · 2.08 KB

AUTH.md

File metadata and controls

43 lines (29 loc) · 2.08 KB

Authentication & multi-tenant

How Oche resolves principals today and how to upgrade to Neon JWT RLS.

Current model (Tier 4)

  1. API key - x-oche-owner header or ?key= (WebSocket). Sources:
    • Built-in demo keys (demo-key-a, demo-key-b) → seed owners A/B
    • OCHE_API_KEYS JSON in Worker env (local: .oche-keys.json)
    • Hashed rows in api_keys table (created via /auth/keys UI)
  2. JWT - Authorization: Bearer <token> or ?token= (WebSocket). Minted by POST /auth/token using OCHE_JWT_SECRET (HS256, 1h TTL).
  3. RLS - Worker still calls withPrincipal() → SET LOCAL app.current_owner. Policies unchanged; JWT/API key only affects which owner id is set.

SPA flow

  • AuthProvider exchanges the selected venue key for a JWT on load/switch.
  • OwnerSwitcher toggles demo-key-a / demo-key-b (RLS demo).
  • /settings/keys - create/revoke hashed API keys (plaintext shown once).

Env

Variable Where Purpose
OCHE_JWT_SECRET .env, Wrangler secret (staging/prod) Sign/verify JWTs
OCHE_API_KEYS apps/api/.dev.vars Extra key → owner map (local)

Generate local keys: npm run keys:generate

Production upgrade - Neon JWT + auth.user_id()

Replace the GUC stand-in so Postgres reads the subject from a verified JWT:

  1. Enable Neon RLS on the project.
  2. Forward the user JWT on the DB connection (Hyperdrive + Authorization or Neon Auth).
  3. Swap Drizzle policies to authenticatedRole + authUid(ownerId) - see docs/examples/neon-jwt-rls.sql.
  4. Drop withPrincipal() GUC; Worker verifies OIDC/JWT once, DB enforces via auth.user_id().

Alternatives: Clerk / Cloudflare Access at the edge → same pattern (verify JWT, pass sub to RLS).

Related