Files
ajet-chat/auth-gw/plan.md
2026-02-17 00:23:25 -05:00

90 lines
3.7 KiB
Markdown

# Auth Gateway Plan
## Overview
Clojure-based edge gateway. All external traffic enters here.
Authenticates requests, then proxies to internal services.
## Stack
- http-kit (HTTP server + async reverse proxy)
- reitit (route matching to determine target service)
- Ring middleware (CORS, rate limiting, logging)
- next.jdbc + HoneySQL (via shared/) for session/token DB lookups
## Responsibilities
- TLS termination (or sit behind nginx for TLS in prod)
- Token validation / session lookup (custom DB reads)
- Authorization (permission checks per route)
- Rate limiting (per-user, per-IP)
- Route authenticated requests to internal services:
- `/api/*` → API service
- `/` + web routes → Web session manager
- `/ws/tui/*` → TUI session manager
- `/ws/mobile/*` → Mobile session manager (future)
- Session creation on login (custom DB writes)
- Audit logging
## Auth Flow
### OAuth Login (v1)
1. Client redirects to `/auth/oauth/:provider` (e.g., `/auth/oauth/github`)
2. Auth GW redirects to provider's OAuth authorization URL
3. Provider redirects back to `/auth/oauth/:provider/callback` with auth code
4. Auth GW exchanges code for access token, fetches user profile from provider
5. Auth GW creates/links user + `oauth_accounts` row, creates session in DB
6. Auth GW sets session cookie and redirects to app
### Login Page
Auth GW owns the login page — Web SM never sees unauthenticated users.
Renders a minimal page with OAuth provider buttons (GitHub, Gitea) and
redirects to the appropriate SSO flow. After OAuth callback completes,
Auth GW sets the session cookie and redirects back to the app.
### Token Format
- Session tokens: 32 random bytes (256 bits of entropy), encoded as base64url
- Stored in DB as bcrypt hash (`token_hash` column in `sessions` table)
- Client sends raw base64url token; Auth GW hashes and looks up the match
### Session Lifecycle
- Rolling expiry: session TTL extends on each authenticated request
- Cookie attributes (web clients): `HttpOnly`, `Secure`, `SameSite=Strict`
- CLI/mobile: raw token in `Authorization: Bearer <token>` header
### Session Validation
1. Client sends request with token (Authorization header or cookie)
2. Auth GW hashes token with bcrypt, looks up `token_hash` in `sessions`
3. If valid: extend expiry, attach user context headers (`X-User-Id`, `X-User-Role`), proxy to target service
4. If invalid/expired: 401 response
### First-User Bootstrap
On first server setup (no communities exist in DB):
1. Auth GW login page shows a community creation form alongside OAuth buttons
2. First user authenticates via OAuth, creates the initial community, becomes its owner
3. After initial community exists, new users must be invited by an existing member (invite-only)
### Future: Email-Based Local Auth
- Email + magic link or email + password (requires email infrastructure)
- Will add `credentials` table when implemented
- OAuth remains primary, local auth is an alternative for self-hosted deployments
## Request Routing
Auth GW generates a unique `X-Trace-Id` header on each inbound request.
All downstream services propagate the trace ID through the call graph.
## Protocols Handled
- **HTTPS**: standard request/response proxy
- **SSE**: authenticate on initial connection, then pass through to session managers
## TODO
- [ ] http-kit reverse proxy setup
- [ ] Route table: path prefix → internal service host:port
- [ ] Token/session DB schema (in shared/)
- [ ] Token validation middleware
- [ ] OAuth flow: GitHub provider (redirect → callback → session creation)
- [ ] OAuth flow: Gitea provider
- [ ] `oauth_accounts` table: link OAuth identities to users
- [ ] SSE connection authentication
- [ ] Rate limiting middleware
- [ ] Logout endpoint (delete session)
- [ ] CORS configuration
- [ ] Audit logging