Skip to content

πŸ” Authentication SystemΒΆ

🎯 Overview¢

The Authentication System provides secure API access through API Keys, enabling programmatic interaction with Continuum's services. It supports role-based access control, key expiration, and application-specific authentication.

πŸ“‹ PurposeΒΆ

The Authentication System enables: - API Key Management: Generate, revoke, and manage API keys - Role-Based Access: API keys inherit permissions from assigned roles - Application Isolation: Keys are specific to each application - Expiration Control: Set expiration times for security - Secure Token Generation: Cryptographically secure key generation

πŸ—οΈ ArchitectureΒΆ

graph TB
    Request[API Request]

    subgraph "Authentication Flow"
        AuthHeader{Authorization<br/>Header?}
        KeyValidator[API Key Validator]
        TokenVerifier[Token Verifier]
        RoleResolver[Role Resolver]
    end

    subgraph "Key Management"
        KeyGenerator[Key Generator]
        KeyStorage[(Key Storage)]
        KeyRotation[Key Rotation]
    end

    subgraph "Access Control"
        PermissionCheck{Has Permission?}
        ACL[ACL System]
        ResourceAccess[Resource Access]
    end

    Request --> AuthHeader
    AuthHeader -->|Yes| KeyValidator
    AuthHeader -->|No| Reject[401 Unauthorized]

    KeyValidator --> TokenVerifier
    TokenVerifier -->|Valid| RoleResolver
    TokenVerifier -->|Invalid| Reject

    RoleResolver --> PermissionCheck
    PermissionCheck -->|Yes| ResourceAccess
    PermissionCheck -->|No| Forbidden[403 Forbidden]

    KeyGenerator --> KeyStorage
    KeyStorage --> KeyValidator
    KeyRotation --> KeyStorage

    RoleResolver --> ACL
    ACL --> PermissionCheck

    classDef auth fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef mgmt fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
    classDef acl fill:#fff3e0,stroke:#e65100,stroke-width:2px
    classDef error fill:#ffebee,stroke:#c62828,stroke-width:2px

    class AuthHeader,KeyValidator,TokenVerifier,RoleResolver auth
    class KeyGenerator,KeyStorage,KeyRotation mgmt
    class PermissionCheck,ACL,ResourceAccess acl
    class Reject,Forbidden error

πŸ”‘ API KeysΒΆ

πŸ“‹ What are API Keys?ΒΆ

API Keys are secure tokens that authenticate API requests without requiring user credentials. They: - Are long, cryptographically random strings - Are tied to a specific role (which defines permissions) - Are application-specific - Can have expiration dates - Are stored hashed in the database

🎯 Key Properties¢

Property Description Example
Token The actual API key string eyJhbGc...
Role Associated role name admin, editor
Application Which app the key belongs to main, marketing-app
Expires In Expiration duration 7d, 30d, never
Created At Key creation timestamp 2025-01-15T10:00:00Z
Last Used Last usage timestamp 2025-01-20T14:30:00Z

πŸ› οΈ API Key ManagementΒΆ

βž• Create API KeyΒΆ

Using the UI: 1. Navigate to Settings β†’ Plugins β†’ API Keys 2. Click "Add API Key" 3. Select a role (defines permissions) 4. Set expiration time (optional) 5. Click "Save" 6. Copy the key immediately (shown only once)

Using the API:

POST /api/apiKeys:create
Authorization: Bearer {existing-user-token}
X-App: main
Content-Type: application/json

{
  "role": {
    "name": "admin"
  },
  "expiresIn": "30d"
}

Response:

{
  "data": {
    "id": 5,
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
    "role": "admin",
    "expiresAt": "2025-02-14T10:00:00.000Z",
    "createdAt": "2025-01-15T10:00:00.000Z"
  }
}

⚠️ Important: Save the token immediately - it cannot be retrieved again for security reasons.

πŸ“‹ List API KeysΒΆ

GET /api/apiKeys:list
Authorization: Bearer {api-key}
X-App: main

Response:

{
  "data": [
    {
      "id": 1,
      "name": "Production API Key",
      "role": "admin",
      "expiresAt": "2025-12-31T23:59:59.000Z",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "lastUsedAt": "2025-01-20T14:30:00.000Z"
    },
    {
      "id": 2,
      "name": "Development Key",
      "role": "developer",
      "expiresAt": null,
      "createdAt": "2025-01-10T08:00:00.000Z",
      "lastUsedAt": "2025-01-20T12:15:00.000Z"
    }
  ]
}

Note: The actual token is never returned in list operations for security.

πŸ—‘οΈ Revoke API KeyΒΆ

POST /api/apiKeys:destroy?filterByTk=5
Authorization: Bearer {api-key}
X-App: main

This immediately invalidates the API key. All subsequent requests with that key will fail.

πŸ”„ Rotate API KeyΒΆ

Best practice: Periodically rotate API keys for security.

# Create new key
POST /api/apiKeys:create
X-App: main
{
  "role": {"name": "admin"},
  "expiresIn": "30d"
}

# Update applications to use new key
# Verify new key works
# Delete old key

POST /api/apiKeys:destroy?filterByTk={old-key-id}
X-App: main

πŸ”§ Using API KeysΒΆ

πŸ“‘ Making Authenticated RequestsΒΆ

Include the API key in the Authorization header:

curl 'https://continuum.example.com/api/articles:list' \
  -H 'Authorization: Bearer {your-api-key}' \
  -H 'X-App: main'

🌐 Application-Specific Keys¢

API keys are specific to the application they were created in:

# Create key for main application
POST /api/apiKeys:create
Authorization: Bearer {user-token}
X-App: main
{
  "role": {"name": "admin"}
}

# Create key for sub-application
POST /api/apiKeys:create
Authorization: Bearer {user-token}
X-App: marketing-platform
{
  "role": {"name": "editor"}
}

Important: Keys from main app cannot access marketing-platform and vice versa.

πŸ“ Example RequestsΒΆ

List Records:

GET /api/products:list
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
X-App: main

Create Record:

POST /api/products:create
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
X-App: main
Content-Type: application/json

{
  "name": "Laptop",
  "price": 999.99
}

Update Record:

POST /api/products:update?filterByTk=1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
X-App: main
Content-Type: application/json

{
  "price": 899.99
}

⏰ Expiration Management¢

πŸ• Expiration FormatsΒΆ

When creating API keys, you can specify expiration using:

Format Description Example
{n}h Hours 24h = 24 hours
{n}d Days 7d = 7 days
{n}w Weeks 2w = 2 weeks
{n}m Months 3m = 3 months
{n}y Years 1y = 1 year
never No expiration Key never expires

Examples:

# 1 hour expiration
{"expiresIn": "1h"}

# 30 days expiration
{"expiresIn": "30d"}

# 1 year expiration
{"expiresIn": "1y"}

# Never expires
{"expiresIn": "never"}

πŸ”” Expiration HandlingΒΆ

When an API key expires: - All requests with that key return 401 Unauthorized - The key remains in the database but is marked as expired - You can see expired keys in the list - Create a new key to replace the expired one

πŸ” Security ConfigurationΒΆ

πŸ”‘ APP_KEY Environment VariableΒΆ

Critical: Set the APP_KEY environment variable before generating API keys.

# .env
APP_KEY=your-secret-key-here-minimum-32-characters-long

Why it matters: - API keys are signed using APP_KEY - If APP_KEY changes, all existing keys become invalid - Without APP_KEY, keys are invalidated on server restart

Generating a secure APP_KEY:

# Generate a random 64-character key
openssl rand -hex 32

πŸ›‘οΈ Security Best PracticesΒΆ

DO: - βœ… Set and persist APP_KEY in production - βœ… Use HTTPS for all API requests - βœ… Store API keys securely (environment variables, secrets management) - βœ… Use different keys for different environments - βœ… Set appropriate expiration times - βœ… Rotate keys periodically - βœ… Revoke unused or compromised keys immediately - βœ… Use least-privilege roles for API keys

DON'T: - ❌ Commit API keys to version control - ❌ Share API keys between applications - ❌ Use the same key for development and production - ❌ Create keys without expiration in production - ❌ Give API keys more permissions than needed - ❌ Expose API keys in client-side code - ❌ Log API keys in application logs

🎯 Access Levels¢

Continuum defines three main access levels:

1️⃣ Public AccessΒΆ

No authentication required. Anyone can access.

// Configuration (internal)
acl.allow('articles', 'list', 'public');
acl.allow('articles', 'get', 'public');

Use Cases: - Public blog posts - Public product catalog - Public documentation

2️⃣ Logged In (loggedIn)ΒΆ

Requires valid API key or user session.

acl.allow('articles', 'create', 'loggedIn');
acl.allow('articles', 'update', 'loggedIn');

Use Cases: - Creating content - Updating own records - Accessing user-specific data

3️⃣ Configure Access (allowConfigure)ΒΆ

Requires administrative permissions.

acl.allow('collections', '*', 'allowConfigure');
acl.allow('apiKeys', '*', 'allowConfigure');

Use Cases: - Managing collections - Creating API keys - System configuration

πŸ”— Integration with RolesΒΆ

API keys inherit all permissions from their associated role.

πŸ“‹ Example Role ConfigurationΒΆ

Admin Role: - Full access to all resources - Can create/delete collections - Can manage users and API keys

Editor Role: - Can create/update/delete content - Cannot modify schema - Cannot manage users

Viewer Role: - Read-only access to content - Cannot create or modify data - Cannot access admin functions

🎯 Creating Keys with Different Roles¢

# Admin key - full access
POST /api/apiKeys:create
X-App: main
{
  "role": {"name": "admin"},
  "expiresIn": "30d"
}

# Editor key - content management only
POST /api/apiKeys:create
X-App: main
{
  "role": {"name": "editor"},
  "expiresIn": "7d"
}

# Viewer key - read-only access
POST /api/apiKeys:create
X-App: main
{
  "role": {"name": "viewer"},
  "expiresIn": "1y"
}

πŸ“š SDK SupportΒΆ

JavaScript/TypeScript SDKΒΆ

import { APIClient } from '@nocobase/sdk';

const api = new APIClient({
  baseURL: 'https://continuum.example.com/api',
  headers: {
    'X-App': 'main',
    'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIs...'
  }
});

// Use the API
const articles = await api.resource('articles').list();

Python ExampleΒΆ

import requests

API_KEY = "eyJhbGciOiJIUzI1NiIs..."
BASE_URL = "https://continuum.example.com/api"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "X-App": "main",
    "Content-Type": "application/json"
}

# List articles
response = requests.get(
    f"{BASE_URL}/articles:list",
    headers=headers
)
articles = response.json()

cURL ExampleΒΆ

#!/bin/bash

API_KEY="eyJhbGciOiJIUzI1NiIs..."
BASE_URL="https://continuum.example.com/api"
APP_NAME="main"

# Function to make API requests
api_request() {
    local method=$1
    local endpoint=$2
    local data=$3

    curl -X "$method" \
        -H "Authorization: Bearer $API_KEY" \
        -H "X-App: $APP_NAME" \
        -H "Content-Type: application/json" \
        -d "$data" \
        "$BASE_URL/$endpoint"
}

# List products
api_request GET "products:list"

# Create product
api_request POST "products:create" '{"name":"Laptop","price":999.99}'

πŸ”§ TroubleshootingΒΆ

❌ Error: "Unauthorized" (401)¢

Possible Causes: 1. API key is invalid or malformed 2. API key has expired 3. APP_KEY changed after key was generated 4. Wrong application specified

Solutions:

# Verify key format
echo "Authorization: Bearer {your-key}" | grep "^Authorization: Bearer eyJ"

# Check key expiration
GET /api/apiKeys:list
X-App: main
# Look for your key's expiresAt field

# Generate new key
POST /api/apiKeys:create
X-App: main
{"role": {"name": "admin"}}

❌ Error: "No permissions" (403)¢

Possible Causes: 1. Role lacks required permissions 2. API key's role doesn't allow the operation 3. Resource-level permissions deny access

Solutions:

# Check your role's permissions
GET /api/roles:get?filterByTk={role-name}&appends=permissions
X-App: main

# Create key with higher privileges
POST /api/apiKeys:create
X-App: main
{"role": {"name": "admin"}}

❌ Error: "Application not found"¢

Possible Causes: 1. Wrong X-App header value 2. Application doesn't exist 3. Using key from different application

Solutions:

# List available applications
GET /api/applications:list
X-App: main

# Ensure X-App matches your key's application

❌ API Key Not Working After Server Restart¢

Cause: APP_KEY environment variable not set

Solution:

# Add to .env file
APP_KEY=your-persistent-secret-key

# Restart server
# Regenerate all API keys

πŸ“Š Monitoring & AnalyticsΒΆ

πŸ“ˆ Track API Key UsageΒΆ

GET /api/apiKeys:list?appends=usageStats
X-App: main
Authorization: Bearer {admin-api-key}

Response includes: - Last used timestamp - Total requests count - Failed authentication attempts - Most accessed endpoints

πŸ”” Key Expiration AlertsΒΆ

Set up monitoring for keys expiring soon:

# Get keys expiring in next 7 days
GET /api/apiKeys:list?filter={"expiresAt":{"$gte":"{{now}}","$lte":"{{now+7d}}"}}
X-App: main
  • Permissions System: Fine-grained access control
  • Multi-App Manager: Application-specific authentication
  • API Gateway: Overall API architecture
  • Best Practices: Security and optimization guidelines

Note: Proper API key management is crucial for maintaining security and access control in your Continuum deployment.