Authentication
Clerk-powered authentication with magic links, session tokens, and service-to-service auth.
Authentication
Reeve Cloud uses Clerk for user authentication and a session token system for API access. There are two auth flows: user-facing (Clerk) and service-to-service (shared tokens).
User Authentication (Clerk)
Sign-up / Sign-in
Users authenticate via Clerk with:
- Magic links — Email-based passwordless auth (primary)
- Google OAuth — Sign in with Google
- Email + password — Traditional credentials
After authentication, Clerk issues a JWT that the frontend includes in API requests.
Session Tokens
For long-lived API access (desktop app, gateway connections), the Services API issues session tokens — UUIDs stored in the database:
POST /api/auth/session
Authorization: Bearer <clerk-jwt>
Response:
{
"session_token": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "user_abc123",
"expires_at": "2026-03-29T12:00:00Z"
}All subsequent API calls use the session token:
GET /api/credits/balance
Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000Auth Flow
User → Clerk (magic link) → JWT → Services API → Session Token → All APIsThe session token is what the frontend, desktop app, and gateway use for ongoing authentication. JWTs are only used during the initial auth handshake.
Auth Context
Every authenticated request provides an AuthUser context:
class AuthUser:
user_id: str # Clerk user ID
email: str | None # User email
is_guest: bool # Guest mode flagGuest Mode
For unauthenticated demo access, a guest mode is available:
GET /api/dashboard
X-Guest-ID: guest_demo_123Guest mode provides read-only access to demo data. No write operations are permitted.
Service-to-Service Auth
The gateway communicates with the Services API using a shared token:
POST /api/credits/deduct
X-Reeve-Services-Token: <shared-secret>
Content-Type: application/json
{
"user_id": "user_abc123",
"amount": 0.05
}This token is set via environment variables:
- Gateway:
REEVE_SERVICES_TOKEN - Services:
REEVE_SERVICES_TOKEN
Both must match. The token is generated during deployment and rotated periodically.
Auth validation order
The Services API checks authentication in this order:
- Session token —
Authorization: Bearer <uuid>header - Service token —
X-Reeve-Services-Tokenheader (service-to-service only) - User ID header —
X-User-ID(dev/testing only, disabled in production)
Device Auth (Desktop App)
The desktop app uses a device auth flow:
- Desktop app opens a browser to the Clerk sign-in page
- User authenticates via Clerk
- Clerk redirects back to the desktop app with a token
- Desktop app exchanges the token for a session token
- Session token is stored locally and used for all API calls
// Desktop auth flow (simplified)
const authUrl = `${FRONTEND_URL}/auth/device?redirect=reeve://auth`;
shell.openExternal(authUrl);
// After redirect back:
const sessionToken = await exchangeAuthCode(code);
store.set('sessionToken', sessionToken);Session tokens expire after 30 days of inactivity. The desktop app and frontend handle token refresh automatically via Clerk's session management.
Security Considerations
- All auth tokens are transmitted over HTTPS only
- Session tokens are UUIDs (not JWTs) — they can be revoked server-side instantly
- Clerk handles password hashing, rate limiting, and brute-force protection
- Service-to-service tokens never leave the server-side environment
- CORS is configured to allow only the frontend domain