Authentication

User login and API key management.

User Authentication

Web Application Login

URL: app.twig.soarrow-up-right

Methods:

  1. Email/Password: Standard authentication, JWT session token (7-day expiry)

  2. SSO: SAML 2.0 or OAuth 2.0 redirect to IdP

  3. OAuth: Google, Microsoft (redirect flow)

Flow:

  1. Enter credentials or click OAuth provider button

  2. Server validates, issues JWT

  3. JWT stored in httpOnly cookie

  4. All requests include cookie automatically

Session Details

  • Storage: httpOnly secure cookie (name: twig_session)

  • Expiry: 7 days (refreshed on each request)

  • Refresh: Automatic (silent refresh 1 hour before expiry)

  • Logout: DELETE /api/auth/logout, cookie cleared

Observable behavior: Logged out after 7 days of inactivity. Login again to restore session.

API Authentication

API keys authenticate programmatic requests.

Generate API Key

  1. Settings → API Keys

  2. Click Generate New Key

  3. Fill form:

    • Name: e.g., "Production API" (required)

    • Scopes: Check boxes for Read, Write, Execute, Admin

    • Environment: Live or Test

  4. Click Generate

Result: Key displayed once (format: twigsk_live_a1b2c3... or twigsk_test_x1y2z3...). Copy immediately.

Storage: Store in environment variable:

Use API Key

Include in Authorization header:

Response (success):

Response (auth failure):

API Key Best Practices

Storage:

  • ✅ Environment variables (TWIG_API_KEY=...)

  • ✅ Secrets manager (AWS Secrets Manager, HashiCorp Vault)

  • ❌ Hardcoded in source code

  • ❌ Committed to git repos

  • ❌ Shared in Slack/email

Key Management:

  • Use separate keys for dev/staging/prod environments

  • Rotate every 90 days (generate new, update apps, delete old)

  • Delete unused keys immediately

  • Monitor usage: Settings → API Keys → [Key Name] → Usage tab

Permissions:

  • Grant minimum required scopes

  • Production keys: Execute only (no Write/Admin)

  • CI/CD keys: Read only for testing

API Key Scopes

Scope
Permissions
Use Case

Read

GET /agents, /data-sources, /interactions

Analytics, monitoring dashboards

Write

POST/PUT/DELETE agents, data sources

Admin tools, setup automation

Execute

POST /query, /chat

Production apps, user-facing features

Admin

All endpoints including org settings

Full admin access, avoid for apps

Observable behavior: API returns 403 Forbidden if scope insufficient:

External API Keys

Store third-party service credentials for custom model usage.

Supported Providers

  • OpenAI: For bring-your-own-key (BYOK) usage, avoids Twig's shared pool

  • Anthropic: For Claude models

  • Custom LLM: Any OpenAI-compatible API endpoint

Add External Key

  1. Settings → External API Keys

  2. Click Add Key

  3. Fill form:

    • Provider: Dropdown (OpenAI, Anthropic, Custom)

    • API Key: Paste key

    • Endpoint (Custom only): e.g., https://your-llm.com/v1

  4. Click Save

Security: Keys encrypted at rest (AES-256), never logged

Usage: Agent Configuration → Model → Select "Use my OpenAI key" (dropdown)

Observable behavior: Queries use your key instead of Twig's. Billing goes to your OpenAI/Anthropic account, not Twig.

SSO Integration

SAML/OAuth for enterprise user authentication.

Supported Protocols

  • SAML 2.0: Okta, Azure AD, Google Workspace, OneLogin, Auth0

  • OAuth 2.0: Google Workspace, Microsoft 365

  • OIDC: OpenID Connect providers

Setup Process

Prerequisites: Enterprise plan, domain verified

Steps:

  1. Email [email protected] with:

    • IdP type (Okta, Azure AD, etc.)

    • SSO metadata URL or XML file

    • Attribute mapping (email → NameID)

  2. Twig configures SSO (1-2 business days)

  3. Test with 1-2 pilot users

  4. Enable for org: Settings → Authentication → Enforce SSO (toggle)

Post-setup:

  • Users go to app.twig.so → "Sign in with SSO"

  • Enter email → redirected to IdP → authenticated → redirected back

  • Session managed as normal (7-day expiry)

Failure scenarios:

  • Invalid SAML assertion → "Authentication failed" error page

  • Email not in allowed domains → "Unauthorized domain" error

See SSO Setup Guidearrow-up-right for IdP-specific instructions.

OAuth for Data Connectors

Third-party service authentication (Google Drive, Slack, etc.).

OAuth Flow

  1. Data → Add Data Source → Select connector (e.g., Google Drive)

  2. Click Connect

  3. Redirected to Google OAuth consent screen

  4. Grant permissions (read files)

  5. Redirected to app.twig.so

  6. Access token stored, data source status: "Connected"

Tokens:

  • Access token: Short-lived (1 hour), used for API requests

  • Refresh token: Long-lived (no expiry), auto-refreshes access token

  • Storage: Encrypted in PostgreSQL oauth_tokens table

Revoke access: Data → [Source] → Settings → Disconnect (deletes tokens from Twig and revokes at provider)

Observable failure: If refresh token invalid (user revoked in Google), data source status: "Connection failed". Reconnect required.

Security

Token Security

Encryption:

  • API keys: Hashed with bcrypt (cost factor: 12) before storage

  • OAuth tokens: AES-256-GCM encryption at rest

  • Session JWTs: HMAC-SHA256 signed, verified on each request

Transport:

  • TLS 1.3 required (TLS 1.2 minimum)

  • HTTPS only (HTTP redirects to HTTPS)

  • HSTS header enabled (max-age: 31536000)

Verification: All API keys checked against PostgreSQL api_keys table on each request (cached in Redis for 5 minutes)

Rate Limiting

Limits by scope:

  • Execute: 100 requests/minute

  • Write: 10 requests/minute

  • Read: 200 requests/minute

  • Admin: 50 requests/minute

Implementation: Token bucket algorithm, enforced at API gateway (Cloudflare Workers)

Response when exceeded:

HTTP status: 429 Too Many Requests

Headers:

Custom limits: Enterprise plan can request increases. Contact support with use case.

IP Allowlisting

Available on: Enterprise plan only

Setup: Settings → Security → IP Allowlist → Add range

Format: CIDR notation (e.g., 192.168.1.0/24, 10.0.0.5/32)

Enforcement: API gateway blocks requests from IPs not in list (returns 403 Forbidden)

Audit: All blocked attempts logged: Settings → Security → Access Logs

Troubleshooting

Error: Invalid API Key

Symptom: API returns 401 with:

Diagnostic steps:

  1. Verify key format: Must start with twigsk_live_ or twigsk_test_

  2. Check header: Authorization: Bearer twigsk_live_... (note "Bearer" prefix)

  3. Settings → API Keys → verify key not deleted

Common mistakes:

  • Missing "Bearer" prefix in Authorization header

  • Using test key (twigsk_test_) against production API

  • Extra whitespace in key

Fix: Regenerate key if lost, update header format.

Error: Token Expired

Symptom: Web UI redirects to login after period of inactivity

Cause: Session JWT expired (7-day TTL)

Fix: Log in again. Session auto-refreshes if you use UI within 7 days.

API users: This doesn't apply to API keys (no expiry).

Error: Insufficient Permissions

Symptom: API returns 403 with:

Diagnostic steps:

  1. Settings → API Keys → [Your Key] → check Scopes section

  2. Verify required scope in error message

  3. Check if key belongs to correct organization

Fix:

  • Delete key, generate new one with correct scopes

  • Or: Contact org admin to regenerate with proper scopes

Error: Rate Limit Exceeded

Symptom: 429 response after burst of requests

Diagnostic steps:

  1. Check response headers:

    • X-RateLimit-Limit: Your limit (e.g., 100)

    • X-RateLimit-Reset: Unix timestamp when reset occurs

  2. Calculate wait time: reset_timestamp - current_timestamp

Fix:

  • Implement exponential backoff in your client

  • Reduce request frequency

  • Enterprise: Request limit increase from support

SSO Login Fails

Symptom: Redirected to error page after IdP authentication

Diagnostic steps:

  1. Check error message (e.g., "Invalid SAML assertion", "Email domain not allowed")

  2. Settings → Authentication → SSO Config → verify IdP metadata URL still valid

  3. Test SAML response with browser dev tools (Network tab)

Common issues:

  • Email attribute not mapped correctly (NameID must contain email)

  • SAML certificate expired at IdP

  • User's email domain not in allowed list

Fix: Contact [email protected] with SAML response XML for diagnosis.

Next Steps

Quick Start Guide - Create your first agent

REST API Reference - API endpoint documentation

Security Best Practices - Secure your deployment

Last updated