Overview
Auth Flow
DreamLake uses a two-token authentication system: a short-lived vuer-auth token for identity, exchanged for a long-lived dreamlake JWT for API access.
Flow
Browser / CLI
│
├── 1. Login via vuer-auth (OAuth / device flow)
│ → receives vuer-auth JWT
│
├── 2. POST /auth/exchange
│ Authorization: Bearer <vuer-auth-token>
│ → server verifies via JWKS
│ → finds or creates User + Namespace
│ → returns dreamlake JWT
│
└── 3. All subsequent API calls
Authorization: Bearer <dreamlake-token>Token Details
| Token | Issuer | Lifetime | Contains |
|---|---|---|---|
| vuer-auth JWT | vuer-auth server | Short (minutes) | sub, email, name, username, OIDC claims |
| dreamlake JWT | dreamlake-server | Long (days) | sub, userId, userName, namespace info |
First Login Side Effects
On POST /auth/exchange, if the user doesn't exist yet:
- User record created from OIDC claims (
sub,email,name, etc.) - Namespace created with
slug = usernameanduserId = sub
Both are idempotent — calling /auth/exchange or /auth/me multiple times is safe.
CLI Authentication
# Device auth flow — opens browser
dreamlake login --url http://localhost:10334
# Or set token directly
export DREAMLAKE_API_KEY=<dreamlake-jwt>
export DREAMLAKE_REMOTE=http://localhost:10334JWT Middleware
All endpoints under the protected scope require a valid dreamlake JWT via the authenticateJWT preHandler hook. The decoded claims are available as request.user:
request.user = {
sub: "vuer-auth-user-id",
userId: "dreamlake-user-id",
userName: "alice",
email: "alice@example.com",
// ...
}