Authentication & Multi-Tenancy

chevron-rightRelevant source fileshashtag

Purpose & Scope

This document describes Automatos AI's authentication and multi-tenancy architecture. It covers Clerk JWT-based authentication, workspace-scoped data isolation, and secure credential management across the platform.

For workspace creation and management UI, see Workspace Management. For credential storage and resolution strategies, see Credentials Management. For API security and rate limiting, see Backend Architecture.


Authentication Architecture

Clerk JWT Integration

Automatos AI uses Clerk for authentication, providing secure JWT-based identity verification without requiring password management infrastructure. Authentication is optional during local development but required in production.

Configuration (config.py:168-175):

CLERK_SECRET_KEY: str = os.getenv("CLERK_SECRET_KEY")
CLERK_PUBLISHABLE_KEY: str = os.getenv("NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY")
CLERK_JWKS_URL: str = os.getenv("CLERK_JWKS_URL")
CLERK_AUDIENCE: str = os.getenv("CLERK_AUDIENCE", "")

The system enforces authentication via REQUIRE_AUTH flag (config.py:87), which defaults to true in production but can be disabled for local development.

Sources: orchestrator/config.py:168-175, orchestrator/config.py:87


Authentication Flow

spinner

Authentication Steps:

  1. Frontend Authentication: User authenticates through Clerk's UI components (/sign-in, /sign-up)

  2. JWT Issuance: Clerk issues a JWT token to the authenticated user

  3. Token Retrieval: Frontend calls getToken() from Clerk's React SDK

  4. Request Headers: Frontend includes Authorization: Bearer {JWT} and X-Workspace-ID headers

  5. JWT Verification: Backend validates JWT signature using Clerk's JWKS endpoint

  6. Workspace Validation: Backend confirms user's membership in the specified workspace

  7. Request Context: Successful validation creates a RequestContext with user_id and workspace_id

Sources: orchestrator/main.py:118-122, orchestrator/config.py:168-175, frontend/lib/api-client.ts:160-163


Request Context & Middleware

Middleware Pipeline

Every API request flows through a standardized middleware pipeline that enforces authentication, workspace isolation, and security policies.

spinner

Middleware Execution Order (main.py:555-642):

  1. CORS Middleware (line 560): Validates origin against allowed list

  2. Rate Limiting (line 583): Enforces 60 requests/minute per IP (configurable)

  3. Body Size Limit (line 603): Prevents payload too large (10MB default, 50MB for uploads)

  4. Security Headers (line 617): Adds CSP, X-Frame-Options, HSTS in production

  5. Request ID (line 632): Assigns unique ID for distributed tracing

  6. API Tracking (line 643): Records metrics to api_call_stats dict

  7. Authentication (implicit): Enforced by dependency injection in route handlers

Sources: orchestrator/main.py:555-688, orchestrator/main.py:583-596


Request Context Resolution

The get_request_context_hybrid dependency provides workspace-aware authentication to route handlers.

spinner

Workspace Resolution Priority (from highest to lowest):

  1. X-Workspace-ID Header: Explicitly specified workspace (validated against user membership)

  2. DEFAULT_WORKSPACE_ID Environment Variable: Fallback for requests without workspace header

  3. DEFAULT_TENANT_ID Constant: UUID 00000000-0000-0000-0000-000000000000 for single-tenant mode

Sources: orchestrator/core/auth/hybrid.py:1-200, orchestrator/config.py:21-23, orchestrator/config.py:173-174


Multi-Tenancy Architecture

Five-Layer Data Isolation

Automatos AI implements workspace isolation across five infrastructure layers to ensure complete tenant separation.

spinner

Sources: Diagram 8 from high-level system diagrams


Database Isolation

All major tables include a workspace_id column with foreign key constraints to the workspaces table. Queries automatically filter by the authenticated user's workspace.

Example Table Structure (core/models/core.py:1-500):

Query Pattern (api/agents.py:50-200):

Marketplace vs Workspace Items:

The owner_type field distinguishes shared marketplace items from workspace-private items:

  • owner_type = "marketplace": Globally available (e.g., community plugins, personas)

  • owner_type = "workspace": Private to the owning workspace

Sources: orchestrator/core/models/core.py:1-500, orchestrator/api/agents.py:1-300


S3 Storage Isolation

All S3 objects use workspace-prefixed keys to prevent cross-tenant access. Vector embeddings are stored in per-workspace buckets.

S3 Key Structure (config.py:246-260):

Resource
Key Pattern
Example

Documents

workspaces/{workspace_id}/documents/{doc_id}/

workspaces/abc123/documents/report.pdf

Vectors

Separate bucket per workspace

automatos-vectors-abc123

Recipe Logs

workspaces/{workspace_id}/logs/{execution_id}/

workspaces/abc123/logs/exec-456.json

Generated Images

workspaces/{workspace_id}/images/{image_id}

workspaces/abc123/images/chart.png

Configuration (config.py:252-260):

Sources: orchestrator/config.py:246-260, orchestrator/modules/rag/service.py:1-550


Redis Isolation

Redis keys use workspace-scoped prefixes to prevent cache leakage between tenants.

Key Naming Conventions (core/redis/client.py:1-200):

Redis Configuration with Security (docker-compose.yml:48-73):

The Redis instance is hardened by disabling dangerous commands (FLUSHDB, FLUSHALL, DEBUG) that could wipe data if exposed.

Sources: orchestrator/core/redis/client.py:66-119, docker-compose.yml:48-73


Filesystem Isolation

The workspace worker service isolates code execution in per-workspace directories with quota enforcement and path safety validation.

Volume Configuration (docker-compose.yml:174-217):

Path Safety Validation (workspace-worker service):

Security Policies:

  1. Path Safety: Blocks .., symlinks, absolute paths

  2. Command Whitelist: Only approved binaries can execute

  3. Storage Quotas: Default 5GB per workspace (configurable)

  4. Environment Sandbox: Stripped PATH, no host variables

  5. Resource Limits: CPU and memory limits enforced by Docker

Sources: docker-compose.yml:174-217, orchestrator/config.py:219-226


Credential Management

Credential Types & Storage

Automatos AI supports multiple credential types with secure encrypted storage. Credentials are scoped to workspaces and encrypted at rest.

spinner

Credential Table Schema:

Encryption Configuration (config.py:175):

Sources: orchestrator/config.py:175, orchestrator/core/database/load_seed_data.py:62-103


Six-Level Credential Resolution

When agents request LLM credentials, the system follows a six-level fallback strategy to maximize availability while respecting workspace boundaries.

spinner

Resolution Strategy (implemented in LLMManager):

  1. Agent-Specific Credential: Check agent.model_config.credentials

  2. Workspace Default Credential: Query credentials table filtered by workspace_id

  3. System Settings Credential: Check system_settings table (admin-configured defaults)

  4. User API Key (BYOK): Check user_api_keys table for bring-your-own-key

  5. Environment Variable: Fall back to OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.

  6. Fallback Provider: If primary provider fails, try secondary (e.g., GPT-4 → Claude)

Sources: orchestrator/core/llm/manager.py:200-650, orchestrator/modules/agents/factory/agent_factory.py:200-650


Composio OAuth Connections

External tool integrations via Composio use workspace-scoped OAuth connections stored in the entity_connections table.

Entity Connection Storage:

Connection Flow:

  1. User clicks "Connect" on a Composio app in the marketplace

  2. Frontend redirects to Composio OAuth consent page with entity_id = workspace_{workspace_id}

  3. User grants permissions

  4. Composio callback stores encrypted tokens in entity_connections

  5. Agents can now use the connected app via ComposioToolService

Permission Validation (modules/tools/execution/unified_executor.py:1-800):

Sources: orchestrator/modules/tools/services/composio_tool_service.py:1-360, orchestrator/modules/tools/execution/unified_executor.py:1-800


Frontend Integration

Clerk React SDK Setup

The frontend uses Clerk's React SDK to handle authentication UI and token management.

Provider Configuration (frontend/app/layout.tsx or similar):

Token Injection (frontend/lib/api-client.ts:157-163):

The ApiClient class accepts a token getter function from components with access to Clerk's useAuth() hook, then includes the JWT in all API requests.

Sources: frontend/lib/api-client.ts:157-163, orchestrator/config.py:168-171


Workspace Selection

The frontend maintains workspace context in localStorage and provides admin override capabilities for support scenarios.

Workspace Header Injection (frontend/lib/api-client.ts:803-816):

Admin Override Functions (frontend/lib/api-client.ts:83-91):

This allows admin users to temporarily impersonate workspaces for debugging without changing localStorage.

Sources: frontend/lib/api-client.ts:803-816, frontend/lib/api-client.ts:83-91


Security Considerations

Production Hardening

Security Headers (main.py:617-627):

Database SSL Enforcement (config.py:46-58):

Production database connections enforce SSL mode unless connecting to local development databases.

Sources: orchestrator/main.py:617-627, orchestrator/config.py:46-58


Rate Limiting

SlowAPI provides IP-based rate limiting with configurable limits per endpoint.

Configuration (main.py:583-596):

The rate limiter respects X-Forwarded-For headers when behind reverse proxies (e.g., Railway, Cloudflare) to correctly identify client IPs.

Sources: orchestrator/main.py:583-596


Request Body Size Limits

The backend enforces different body size limits based on endpoint type to prevent resource exhaustion.

Middleware (main.py:598-614):

Limits:

  • Default: 10MB for API requests

  • Uploads: 50MB for document/plugin uploads

Sources: orchestrator/main.py:598-614


Redis Security Hardening

The Redis instance is hardened by disabling dangerous administrative commands.

Disabled Commands (docker-compose.yml:54-62):

This prevents accidental or malicious data wipes if the Redis instance is exposed (e.g., misconfigured firewall). The CONFIG command is also renamed, breaking redis-cli CONFIG but preventing runtime configuration changes.

Sources: docker-compose.yml:54-62


Environment Configuration

Required Variables

Minimum Configuration (.env.example:1-65):

Sources: orchestrator/.env.example:1-65


Docker Compose Configuration

Backend Service (docker-compose.yml:78-138):

Frontend Service (docker-compose.yml:146-170):

The frontend only receives public-safe environment variables (NEXT_PUBLIC_* prefix). Secrets like CLERK_SECRET_KEY stay server-side only.

Sources: docker-compose.yml:78-170


Development Workflow

Local Development Setup

  1. Copy Environment Template:

  2. Configure Clerk (optional for local dev):

    • Create a Clerk application at https://clerk.com

    • Copy API keys to .env

    • Set REQUIRE_AUTH=false to bypass authentication locally

  3. Start Services:

  4. Access Application:

    • Frontend: http://localhost:3000

    • Backend: http://localhost:8000

    • API Docs: http://localhost:8000/docs

Development Mode Authentication:

When REQUIRE_AUTH=false, the system allows unauthenticated requests and assigns a default workspace ID. This simplifies local testing without requiring Clerk setup.

Sources: orchestrator/config.py:87-88, orchestrator/.env.example:33


Testing Multi-Tenancy

Manual Workspace Testing:

  1. Create multiple workspaces via API or UI

  2. Switch workspace context by changing X-Workspace-ID header

  3. Verify data isolation:

    • Agents from workspace A should not appear in workspace B

    • Document uploads should use workspace-prefixed S3 keys

    • Redis cache keys should include workspace ID

Admin Override Testing (frontend/lib/api-client.ts:83-91):

Sources: frontend/lib/api-client.ts:83-91


Migration from Single-Tenant

Adding Workspace Support to Existing Tables

Migration Template:

Update Query Logic:

Sources: orchestrator/core/models/core.py:1-500


Summary

Component
Isolation Method
Key Configuration

Authentication

Clerk JWT validation

CLERK_SECRET_KEY, CLERK_JWKS_URL

Database

workspace_id column + filters

Foreign key to workspaces table

S3 Storage

Path prefix workspaces/{id}/

Per-workspace vector buckets

Redis Cache

Key prefix workspace:ws:{id}:

Workspace-scoped keys

Filesystem

Volume path /workspaces/{id}/

WORKSPACE_VOLUME_PATH env var

Credentials

Encrypted per workspace

CREDENTIAL_ENCRYPTION_KEY

Rate Limiting

IP-based (60/min default)

SlowAPI middleware

Request Context

get_request_context_hybrid

X-Workspace-ID header

Automatos AI's multi-tenancy architecture ensures complete data isolation through layered security controls, allowing thousands of workspaces to operate securely on shared infrastructure.

Sources: orchestrator/main.py:1-800, orchestrator/config.py:1-423, frontend/lib/api-client.ts:1-1500


Last updated