Authentication
The gateway supports two authentication mechanisms: JWT-based session auth for the dashboard and API token auth for client APIs.
Authentication Modes
| Mode | Used For | Mechanism |
|---|---|---|
| JWT Session | Dashboard UI | HTTP-only cookie |
| API Token | Client APIs (/api/client/v1/*) | Authorization: Bearer <token> |
JWT Session Authentication
Login Flow
- User submits slug + email + password to
POST /api/auth/login - Server finds tenant by slug, switches to tenant database
- Validates email/password against stored bcrypt hash
- Generates JWT with user info, license features, and tenant data
- Sets HTTP-only cookie (
token) - Returns user profile
Registration Flow
- User submits company name, slug, name, email, password to
POST /api/auth/register - Server creates tenant with the given slug
- Creates a new
tenant_{slug}database - Creates user as owner with hashed password
- Assigns default license (FREE)
- Generates JWT and sets cookie
- 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 handlerHeaders injected for authenticated requests:
| Header | Content |
|---|---|
x-user-id | User ObjectId |
x-user-email | User email |
x-user-role | owner, admin, project_admin, user |
x-tenant-id | Tenant ObjectId |
x-tenant-slug | Tenant slug |
x-tenant-db-name | tenant_{slug} |
x-license-type | License tier |
x-features | JSON array of feature flags |
x-request-id | Request 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
- Extract Bearer token from
Authorizationheader - Check cache (SHA-256 hash key, 60s TTL)
- On cache miss: query database, resolve tenant
- Fire-and-forget: update
lastUsedtimestamp - Switch to tenant database
- Ensure default project exists
- Resolve user from token record
- Return
ApiTokenContext
Token Properties
| Field | Description |
|---|---|
token | The raw token string |
userId | Owning user |
tenantId | Owning tenant |
projectId | Scoped project (optional) |
expiresAt | Expiration date (optional) |
lastUsed | Last 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
| Tier | Features | Request Limit |
|---|---|---|
| FREE | 16 features | 1,000/month |
| STARTER | 10 features | 10,000/month |
| PROFESSIONAL | 14 features | 100,000/month |
| ENTERPRISE | All features | Unlimited |
| ON_PREMISE | All features | Unlimited |
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
| Role | Scope |
|---|---|
owner | Full tenant control |
admin | Manage users and settings |
project_admin | Manage assigned projects |
user | Access assigned projects only |
Configuration
| Variable | Default | Description |
|---|---|---|
JWT_SECRET | — | Required. Secret for JWT signing |
JWT_EXPIRES_IN | 7d | JWT expiration duration |
PROVIDER_ENCRYPTION_SECRET | JWT_SECRET | Encryption key for stored credentials |