Reeve
Cloud Platform

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-446655440000

Auth Flow

User → Clerk (magic link) → JWT → Services API → Session Token → All APIs

The 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 flag

Guest Mode

For unauthenticated demo access, a guest mode is available:

GET /api/dashboard
X-Guest-ID: guest_demo_123

Guest 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:

  1. Session tokenAuthorization: Bearer <uuid> header
  2. Service tokenX-Reeve-Services-Token header (service-to-service only)
  3. User ID headerX-User-ID (dev/testing only, disabled in production)

Device Auth (Desktop App)

The desktop app uses a device auth flow:

  1. Desktop app opens a browser to the Clerk sign-in page
  2. User authenticates via Clerk
  3. Clerk redirects back to the desktop app with a token
  4. Desktop app exchanges the token for a session token
  5. 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

On this page