Skip to main content
Consuelo uses JWT-based authentication. This guide covers the complete auth flow.

Authentication Flow

Step 1: Obtain Challenge

Request a signed challenge from the server:
POST /v1/auth/challenge
Content-Type: application/json

{
  "workspaceId": "ws_abc123"
}
Response:
{
  "data": {
    "challenge": "sign_this:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresAt": "2024-01-15T10:30:00Z"
  }
}

Step 2: Sign and Verify

Sign the challenge with your app secret and verify:
POST /v1/auth/verify
Content-Type: application/json

{
  "workspaceId": "ws_abc123",
  "challenge": "sign_this:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "signature": "sha256(challenge + APP_SECRET)"
}
Response:
{
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresIn": 1800
  }
}

Token Structure

Access Token (30 min expiry)

{
  "sub": "user_123",
  "type": "ACCESS",
  "userId": "user_123",
  "workspaceId": "ws_abc123",
  "workspaceMemberId": "wsmember_456",
  "authProvider": "google",
  "isImpersonating": false
}

Refresh Token (60 day expiry)

Long-lived token used to obtain new access tokens. Stored in the database with reuse detection.

Token Refresh

When your access token expires, use the refresh token:
POST /v1/auth/refresh
Content-Type: application/json

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response:
{
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresIn": 1800
  }
}

Security

  • Tokens are signed using your workspace’s secret
  • The secret is derived: sha256(APP_SECRET + workspaceId + tokenType)
  • Refresh tokens are rotation-safe (reused tokens are invalidated)
  • Store tokens securely; never log or expose them
Never share your APP_SECRET. It’s used to derive token secrets for all workspace users.