Skip to Content
ArchitectureAuth Flows

Auth Flows

Three distinct callers reach the platform, each with its own credential type.

Web console (owner / developer)

  1. The browser redirects to the Cognito Hosted UI with PKCE.
  2. The user signs in with a social provider (Google, optionally GitHub / Microsoft Entra) or email/password.
  3. On first confirmation, a post-confirmation Cognito trigger writes the user’s USER#<sub> record (approval_status=pending for self-signups, approved for invited users).
  4. After login, the console’s AuthGuard calls GET /v1/tenants/my. A user with no active tenant is redirected to /onboarding.
  5. Submitting the onboarding form (POST /v1/tenants) provisions the tenant, KMS CMK, Stripe customer/subscription, and free-credit row.

The pre-token-generation trigger injects tenant_id, tenant_role, and platform_role claims into the JWT from the DynamoDB user record.

Claude Code via agent-runner-auth

The apiKeyHelper integration runs agent-runner-auth token. On first use it opens a browser PKCE flow, stores the access and refresh tokens in the OS keychain, and prints the access token to stdout. Subsequent calls return the cached token (~50ms) or silently refresh it.

The OAuth endpoints are Cognito Hosted UI:

EndpointURL
Authorizehttps://auth.<domain>/oauth2/authorize
Tokenhttps://auth.<domain>/oauth2/token
Revokehttps://auth.<domain>/oauth2/revoke
UserInfohttps://auth.<domain>/oauth2/userinfo

Service accounts (CI / Claude Desktop)

Generate an API key (ar_live_...) from the console and pass it as the x-api-key header. The proxy verifies it via bcrypt comparison against the stored hash, then loads tenant_id and limits from the key record.

Proxy authentication invariants

  • The JWKS cache TTL is 1 hour. On JWKS fetch failure the proxy fails over to the DynamoDB key path — it never serves unauthenticated requests.
  • The DynamoDB tenant cache TTL is 60 seconds. A cold Lambda always reads DynamoDB; a warm Lambda may use the in-memory cache. Cache invalidation is not supported — config changes propagate in ≤60s.
  • The credential’s tenant_id must match the tenant resolved from the Host header, or the request is rejected with 403.
Last updated on