Authentication is stateless: the server issues a signed JWT on login and never stores session state. Every request carries the token in an HTTP-only cookie; the server verifies the signature and expiry on each request without any database or cache lookup. This makes horizontal scaling trivial — any replica can handle any request.
Credential storage is pluggable. The initial implementation reads from a local file mounted by Kubernetes from a ConfigMap, which is sufficient for dev and early deployments. The interface is designed so the file-based backend can be swapped for an OIDC/SSO provider without touching the JWT layer or any route handler.
POST /auth/login
│
├─ read userId + password from form body
├─ load credentials from backend (file or SSO)
├─ verify password (bcrypt compare)
├─ invalid → 401, re-render login form with error message
└─ valid → sign JWT → set HttpOnly cookie → redirect to /
Subsequent requests
│
├─ hooks.server.ts reads `session` cookie
├─ verifyToken() checks signature + expiry (no I/O)
├─ valid → populate event.locals.user → proceed
└─ invalid → redirect to /auth/login
GET /auth/logout
│
└─ clear `session` cookie → redirect to /auth/login
AUTH_JWT_SECRET env varexp claim{ username: string } where username is the user's id fieldHttpOnly; SameSite=Lax; Secure; Path=/ cookie named sessionjose.jwtVerify() with no external callsA JSON file mounted into the pod from a Kubernetes ConfigMap:
[
{
"id": "admin",
"passwordHash": "$2b$10$...",
"name": "Admin User",
"email": "admin@example.com",
"workspaces": ["default"]
}
]
Fields: id (required, used as login identifier and stored in JWT), passwordHash (required, bcrypt), name (optional, display name), email (optional), workspaces (optional, list of workspace IDs the user may access; defaults to []).
AUTH_USERS_FILE env varAuth.init() and cached in memory; pod restart required to pick up changeshtpasswd -nbB admin mypassword | cut -d: -f2ConfigMap example:
apiVersion: v1
kind: ConfigMap
metadata:
name: agent-paas-users
namespace: agent-paas
data:
users.json: |
[
{ "id": "admin", "passwordHash": "$2b$10$...", "workspaces": ["default"] }
]
Mount it as a volume at /etc/agent-paas/users.json in the pod spec.
When SSO is required, replace the Auth class with an OIDC-backed implementation that:
{ username: id } payload) so the rest of the system is unaffectedThe Server class wires in the concrete Auth implementation; no route handler or hook needs to change.
AUTH_JWT_SECRET invalidates all existing sessions (users must re-login); this is acceptable for a developer tool with an 8-hour TTL