The authentication and authorization backbone of the CROW platform. Manages user sessions via Better Auth, issues JWTs for internal service communication, handles API key lifecycle, and orchestrates the multi-step onboarding flow.
Worker name: crow-core-auth-service
Domain (prod): internal.auth-api.crowai.dev
Domain (dev): dev.internal.auth-api.crowai.dev
Schema
user
| Column | Type | Notes |
|---|
| id | text PK | Better Auth user ID |
| name | text | |
| email | text | unique |
| emailVerified | boolean | default false |
| image | text | nullable |
| isAnonymous | boolean | default false |
| createdAt | timestamp | |
| updatedAt | timestamp | |
session
| Column | Type | Notes |
|---|
| id | text PK | |
| token | text | unique |
| expiresAt | timestamp | |
| ipAddress | text | nullable |
| userAgent | text | nullable |
| userId | text FK | references user.id |
| activeOrganizationId | text | nullable, set by set-active |
| createdAt | timestamp | |
| updatedAt | timestamp | |
account
| Column | Type | Notes |
|---|
| id | text PK | |
| accountId | text | provider-specific ID |
| providerId | text | credential, google, etc. |
| userId | text FK | references user.id |
| accessToken | text | nullable |
| refreshToken | text | nullable |
| idToken | text | nullable |
| password | text | nullable, hashed |
| scope | text | nullable |
| createdAt | timestamp | |
| updatedAt | timestamp | |
organization
Better Auth organization plugin table.
| Column | Type | Notes |
|---|
| id | text PK | Better Auth org ID |
| name | text | |
| slug | text | unique |
| logo | text | nullable |
| metadata | text | nullable, JSON |
| createdAt | timestamp | |
member
| Column | Type | Notes |
|---|
| id | text PK | |
| organizationId | text FK | references organization.id |
| userId | text FK | references user.id |
| role | text | owner, admin, member |
| createdAt | timestamp | |
invitation
| Column | Type | Notes |
|---|
| id | text PK | |
| organizationId | text FK | |
| email | text | |
| role | text | |
| status | text | default pending |
| expiresAt | timestamp | |
| inviterId | text FK | references user.id |
| createdAt | timestamp | |
apikey
| Column | Type | Notes |
|---|
| id | text PK | |
| name | text | nullable |
| start | text | nullable, key prefix display |
| prefix | text | nullable |
| key | text | hashed key |
| userId | text FK | |
| enabled | boolean | default true |
| rateLimitEnabled | boolean | default false |
| rateLimitTimeWindow | integer | nullable |
| rateLimitMax | integer | nullable |
| requestCount | integer | default 0 |
| remaining | integer | nullable |
| expiresAt | timestamp | nullable |
| permissions | text | nullable, JSON |
| metadata | text | nullable, JSON (includes organizationId) |
| createdAt | timestamp | |
| updatedAt | timestamp | |
onboarding
| Column | Type | Notes |
|---|
| id | text PK | |
| betterAuthUserId | text | |
| betterAuthOrgId | text | nullable |
| orgBuilderId | text | nullable |
| userBuilderId | text | nullable |
| billingBuilderId | text | nullable |
| currentStep | integer | default 1 |
| completedSteps | text | JSON array |
| productSource | text | nullable |
| sources | text | JSON |
| status | text | default in_progress |
| createdAt | timestamp | |
| completedAt | timestamp | nullable |
verification
Better Auth verification tokens (email verify, password reset).
jwks
| Column | Type | Notes |
|---|
| id | text PK | |
| publicKey | text | JWK public key |
| privateKey | text | JWK private key |
| createdAt | timestamp | |
Routes
Better Auth Routes (proxied)
All routes matching /api/v1/auth/{sign-up,sign-in,sign-out,session,get-session,user,callback,verify-email,reset-password,change-password,forgot-password,update-user,organization,invite,token,jwks,api-key}/* are proxied directly to Better Auth's handler.
Notable routes:
POST /api/v1/auth/sign-up/email -- email/password registration
POST /api/v1/auth/sign-in/email -- email/password login
GET /api/v1/auth/get-session -- returns current session + activeOrganizationId
GET /api/v1/auth/token -- returns JWT for the authenticated session
GET /api/v1/auth/jwks -- public JWKS for JWT verification
POST /api/v1/auth/organization/create -- creates org (triggers sync to org+user services)
POST /api/v1/auth/organization/set-active -- sets active org on session
POST /api/v1/auth/api-key/create -- creates an API key
Custom Routes
| Method | Path | Description |
|---|
| POST | /api/v1/auth/api-key/verify | Verifies an API key (internal, requires X-Service-API-Key) |
| POST | /api/v1/auth/api-key/system-token | Issues a system JWT for an API key holder |
| * | /api/v1/auth/jwt/* | JWT-related routes |
| * | /api/v1/auth/onboarding/* | Multi-step onboarding flow management |
| * | /api/v1/auth/onboarding/callbacks/* | Onboarding callback handlers |
| * | /api/v1/auth/team-invitations/* | Team invitation management |
| GET | /health | Health check |
| GET | /ready | Readiness check (includes DB health) |
Environment Variables
| Variable | Example | Notes |
|---|
| ENVIRONMENT | dev | local, dev, prod |
| BETTER_AUTH_URL | https://dev.api.crowai.dev | Base URL for Better Auth |
| PRODUCT_SERVICE_URL | https://dev.internal.products.crowai.dev | |
| AUTH_CLIENT_URL | https://dev.auth.crowai.dev | Redirect URLs |
| NOTIFICATION_SERVICE_URL | https://dev.internal.notifications.crowai.dev | |
| USER_SERVICE_URL | https://dev.internal.users.crowai.dev | |
| BILLING_SERVICE_URL | https://dev.internal.billing.crowai.dev | |
| ORGANIZATION_SERVICE_URL | https://dev.internal.orgs.crowai.dev | |
| DASHBOARD_URL | https://dev.app.crowai.dev | |
Secrets
| Secret | Purpose |
|---|
| BETTER_AUTH_SECRET | Session signing key |
| GOOGLE_CLIENT_ID | Google OAuth client ID |
| GOOGLE_CLIENT_SECRET | Google OAuth client secret |
| SERVICE_API_KEY_USER | Key for calling user service |
| SERVICE_API_KEY_ORGANIZATION | Key for calling org service |
| SERVICE_API_KEY_BILLING | Key for calling billing service |
| SERVICE_API_KEY_NOTIFICATION | Key for calling notification service |
| SERVICE_API_KEY_PRODUCT | Key for calling product service |
| SERVICE_API_KEY_GATEWAY | Accepted from gateway |
| SERVICE_API_KEY_WEB_INGEST | Accepted from web-ingest service |
Bindings
| Binding | Type | Name |
|---|
| DB | D1 | crow-core-auth-service-db |
| PRODUCT_CRAWL_QUEUE | Queue (producer) | crow-product-crawl-queue |
Dependencies
- Outbound: user service (sync), org service (sync), notification service, billing service, product service
- Inbound: gateway (session validation, JWT retrieval), all services (JWKS)
Key Behaviors
- Org create sync: On
POST /organization/create success, the service calls the org service and user service to create corresponding internal records (via syncOrgAndMember)
- Email domain blocklist: Consumer domains (gmail, yahoo, outlook, etc.) are rejected at sign-up
- Rate limiting: Map-based in-memory rate limiter on sign-in, sign-up, api-key/verify, and system JWT endpoints (300 requests max per window)
- Cookie cache: Disabled (
cookieCache: { enabled: false }) to prevent stale session data after set-active