Skip to content

Authentication

The gateway supports two authentication mechanisms: JWT-based session auth for the dashboard and API token auth for client APIs.

Authentication Modes

ModeUsed ForMechanism
JWT SessionDashboard UIHTTP-only cookie
API TokenClient APIs (/api/client/v1/*)Authorization: Bearer <token>

JWT Session Authentication

Login Flow

  1. User submits slug + email + password to POST /api/auth/login
  2. Server finds tenant by slug, switches to tenant database
  3. Validates email/password against stored bcrypt hash
  4. Generates JWT with user info, license features, and tenant data
  5. Sets HTTP-only cookie (token)
  6. Returns user profile

Registration Flow

  1. User submits company name, slug, name, email, password to POST /api/auth/register
  2. Server creates tenant with the given slug
  3. Creates a new tenant_{slug} database
  4. Creates user as owner with hashed password
  5. Assigns default license (FREE)
  6. Generates JWT and sets cookie
  7. Sends welcome email

JWT Payload

typescript
{
  userId: string;
  email: string;
  role: 'owner' | 'admin' | 'project_admin' | 'user';
  tenantId: string;
  tenantSlug: string;
  tenantDbName: string;
  licenseType: string;
  features: string[];
}

The JWT is signed using the jose library (Edge Runtime compatible) with JWT_SECRET.

Middleware Processing

The global middleware (src/middleware.ts) processes every request:

Request → Is public path? → Pass through
        → Is client API? → Skip cookie auth (Bearer handled in route)
        → Extract cookie → Verify JWT → Check license endpoint access
        → Inject headers → Forward to route handler

Headers injected for authenticated requests:

HeaderContent
x-user-idUser ObjectId
x-user-emailUser email
x-user-roleowner, admin, project_admin, user
x-tenant-idTenant ObjectId
x-tenant-slugTenant slug
x-tenant-db-nametenant_{slug}
x-license-typeLicense tier
x-featuresJSON array of feature flags
x-request-idRequest UUID

Public Paths

These paths skip authentication:

  • /login, /register
  • /api/auth/*
  • /api/health/*

API Token Authentication

For programmatic access, tenants create API tokens through the dashboard. These tokens authenticate requests to /api/client/v1/* endpoints.

Usage

bash
curl -X POST https://gateway.example.com/api/client/v1/chat/completions \
  -H "Authorization: Bearer cgt_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}'

requireApiToken Helper

All client API routes use the requireApiToken helper:

typescript
import { requireApiToken, ApiTokenAuthError } from '@/lib/services/apiTokenAuth';

export async function POST(request: NextRequest) {
  try {
    const ctx = await requireApiToken(request);
    // ctx.token, ctx.tokenRecord, ctx.tenant
    // ctx.tenantId, ctx.tenantSlug, ctx.tenantDbName
    // ctx.projectId, ctx.user
  } catch (error) {
    if (error instanceof ApiTokenAuthError) {
      return NextResponse.json({ error: error.message }, { status: error.status });
    }
    throw error;
  }
}

Token Validation Flow

  1. Extract Bearer token from Authorization header
  2. Check cache (SHA-256 hash key, 60s TTL)
  3. On cache miss: query database, resolve tenant
  4. Fire-and-forget: update lastUsed timestamp
  5. Switch to tenant database
  6. Ensure default project exists
  7. Resolve user from token record
  8. Return ApiTokenContext

Token Properties

FieldDescription
tokenThe raw token string
userIdOwning user
tenantIdOwning tenant
projectIdScoped project (optional)
expiresAtExpiration date (optional)
lastUsedLast usage timestamp

License-Based Feature Control

Features are controlled through a license system defined in src/config/policies.json:

typescript
import { LicenseManager } from '@/lib/license/license-manager';

const hasAccess = LicenseManager.hasFeature(licenseType, 'LLM_CHAT');
const canAccessEndpoint = LicenseManager.hasEndpointAccess(licenseType, '/api/models');

License Tiers

TierFeaturesRequest Limit
FREE16 features1,000/month
STARTER10 features10,000/month
PROFESSIONAL14 features100,000/month
ENTERPRISEAll featuresUnlimited
ON_PREMISEAll featuresUnlimited

Feature Endpoint Mapping

Each feature in policies.json maps to API endpoint patterns:

json
{
  "LLM_CHAT": {
    "name": "LLM Chat",
    "endpoints": ["/api/chat/*", "/api/client/v1/chat/*"]
  }
}

The middleware checks these mappings automatically.

User Roles

RoleScope
ownerFull tenant control
adminManage users and settings
project_adminManage assigned projects
userAccess assigned projects only

Configuration

VariableDefaultDescription
JWT_SECRETRequired. Secret for JWT signing
JWT_EXPIRES_IN7dJWT expiration duration
PROVIDER_ENCRYPTION_SECRETJWT_SECRETEncryption key for stored credentials

Community edition is AGPL-3.0. Commercial licensing and support are available separately.