Skip to main content

Overview

Mission Control supports three authentication methods:
  1. Session Cookie - For browser-based access after login
  2. API Key - For headless automation and CLI tools
  3. Google OAuth - For team SSO with admin approval workflow
All authenticated users are assigned one of three roles: viewer, operator, or admin.

Authentication Methods

Role-Based Access Control (RBAC)

Mission Control enforces three permission levels:
{
  "role": "viewer",
  "permissions": [
    "Read agents",
    "Read tasks",
    "Read token usage",
    "Read logs and activities",
    "Read system status"
  ],
  "restrictions": [
    "Cannot create or modify resources",
    "Cannot access admin settings",
    "Cannot manage users"
  ]
}

Role Hierarchy

Roles are hierarchical: viewer < operator < admin
const ROLE_LEVELS = {
  viewer: 0,
  operator: 1,
  admin: 2
};
Endpoints specify minimum required role. For example, POST /api/agents requires operator or higher.

Security Considerations

Follow these security best practices before deploying to production:

Password Requirements

  • Minimum 12 characters
  • Hashed with scrypt (CPU-intensive key derivation)
  • Constant-time comparison to prevent timing attacks
// From auth.ts:208
if (password.length < 12) {
  throw new Error('Password must be at least 12 characters');
}

Session Security

  • Duration: 7 days (604800 seconds)
  • Storage: SQLite user_sessions table
  • Token: 32-byte random hex (64 characters)
  • Cleanup: Expired sessions purged on each login
// From auth.ts:80
const SESSION_DURATION = 7 * 24 * 60 * 60; // 7 days
const token = randomBytes(32).toString('hex');

API Key Security

  • Constant-time comparison prevents timing attacks
  • Never log API keys in application logs
  • Rotate keys regularly
  • Use different keys for dev/staging/production
// From auth.ts:281
if (apiKey && safeCompare(apiKey, process.env.API_KEY || '')) {
  return { id: 0, username: 'api', role: 'admin' };
}

CSRF Protection

Mutating requests validate the Origin header:
// From proxy.ts:74-88
if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(method)) {
  const origin = request.headers.get('origin');
  if (origin) {
    const originHost = new URL(origin).host;
    const requestHost = request.headers.get('host');
    if (originHost !== requestHost) {
      return NextResponse.json(
        { error: 'CSRF origin mismatch' },
        { status: 403 }
      );
    }
  }
}
API key authentication bypasses CSRF checks since keys are header-based.

User Management

Get Current User

curl http://localhost:3000/api/auth/me \
  -H "x-api-key: your-api-key"
Response:
{
  "user": {
    "id": 1,
    "username": "admin",
    "display_name": "Administrator",
    "role": "admin",
    "workspace_id": 1,
    "provider": "local",
    "email": null,
    "avatar_url": null,
    "created_at": 1709587200,
    "last_login_at": 1709673600
  }
}

List Users (Admin)

curl http://localhost:3000/api/auth/users \
  -H "x-api-key: your-api-key"
Response:
{
  "users": [
    {
      "id": 1,
      "username": "admin",
      "display_name": "Administrator",
      "role": "admin",
      "created_at": 1709587200
    },
    {
      "id": 2,
      "username": "operator1",
      "display_name": "Agent Operator",
      "role": "operator",
      "created_at": 1709673600
    }
  ]
}

Create User (Admin)

curl -X POST http://localhost:3000/api/auth/users \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -d '{
    "username": "analyst",
    "password": "secure-password-min-12-chars",
    "display_name": "Data Analyst",
    "role": "viewer",
    "email": "[email protected]"
  }'
Response: 201 Created
{
  "user": {
    "id": 3,
    "username": "analyst",
    "display_name": "Data Analyst",
    "role": "viewer",
    "email": "[email protected]",
    "created_at": 1709760000
  }
}

Update User (Admin)

curl -X PUT http://localhost:3000/api/auth/users \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -d '{
    "id": 3,
    "role": "operator",
    "display_name": "Senior Data Analyst"
  }'

Delete User (Admin)

curl -X DELETE http://localhost:3000/api/auth/users \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -d '{"id": 3}'
Deleting a user destroys all their sessions immediately.

Error Responses

401 Unauthorized

Authentication required but not provided:
{
  "error": "Authentication required"
}
Causes:
  • No session cookie or API key provided
  • Session expired (7 days)
  • Invalid API key

403 Forbidden

Authenticated but insufficient permissions:
{
  "error": "Requires admin role or higher"
}
Causes:
  • Viewer trying to create resources
  • Operator trying to manage users
  • OAuth user not yet approved

409 Conflict

Resource already exists:
{
  "error": "Username already exists"
}

Initial Setup

On first run, Mission Control seeds an admin user from environment variables:
# .env
AUTH_USER=admin
AUTH_PASS=your-secure-password

# Or use base64 if password contains special characters
AUTH_PASS_B64=eW91ci1zZWN1cmUtcGFzc3dvcmQ=
If AUTH_PASS contains # or other shell metacharacters, use quotes or switch to AUTH_PASS_B64.

Generating a Secure Password

# Generate 24-character random password
openssl rand -base64 24

# For base64 encoding
echo -n "your-password" | base64

Best Practices

1

Use Strong Credentials

  • Passwords: Minimum 12 characters, mix of letters/numbers/symbols
  • API keys: At least 32 random characters
  • Rotate API keys quarterly
2

Deploy Behind Reverse Proxy

Use Caddy, nginx, or Traefik with automatic TLS:
server {
  listen 443 ssl http2;
  server_name mission-control.example.com;
  
  ssl_certificate /path/to/cert.pem;
  ssl_certificate_key /path/to/key.pem;
  
  location / {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}
3

Configure Host Allowlist

Restrict network access in production:
MC_ALLOWED_HOSTS=mission-control.example.com,*.internal.corp
4

Enable Audit Logging

Track administrative actions:
curl http://localhost:3000/api/audit \
  -H "x-api-key: your-api-key"

Next Steps

Agents API

Manage agent lifecycle and status

Tasks API

Create and assign tasks to agents

Webhooks

Configure outbound event notifications

Token Tracking

Monitor LLM token usage and costs

Build docs developers (and LLMs) love