API Key Management

Created: Tue 29 Jul 2025 10:45:00 CEST
Updated: Thu 11 Jun 2026 15:46:06 CEST - Key rotation performed (director-prod-v1 → gateway-prod-v2); canonical env var renamed DIRECTOR_API_KEY → GATEWAY_API_KEY (old name accepted as fallback during transition); auth module renamed director_auth.py → gateway_auth.py; new key prefix gw_
Document Version: 1.1 - Gateway key rotation and naming update
Security Classification: Internal Security Documentation
Target Audience: DevOps Engineers, Security Team, System Administrators
Author: Paul Wisén

Overview

This document describes the secure generation and management of API keys for the Plings ecosystem, specifically for service-to-service authentication between the Gateway (s.plings.io) and Backend API (api.plings.io).

Security Principles

  1. Never generate API keys in chat systems (Claude, ChatGPT, etc.)
  2. Never commit API keys to version control
  3. Rotate keys regularly (recommended: every 90 days)
  4. Use different keys for each environment (dev, staging, production)
  5. Monitor key usage for anomalies

Generating Secure API Keys

# Generate a 64-character hex string
openssl rand -hex 32

# Add the gw_ prefix for Gateway keys
echo "gw_$(openssl rand -hex 32)"

Method 2: Using Python

import secrets
api_key = f"gw_{secrets.token_hex(32)}"
print(api_key)

Method 3: Using Node.js

const crypto = require('crypto');
const apiKey = `gw_${crypto.randomBytes(32).toString('hex')}`;
console.log(apiKey);

Key Format Standards

Gateway API Keys

Future Key Types

Configuration Locations

Gateway Service (s.plings.io)

  1. Vercel Dashboard: Plings-Gateway project → Settings → Environment Variables
  2. Variable Name: GATEWAY_API_KEY (canonical). DIRECTOR_API_KEY is still read as a fallback by the Gateway code during the rename transition.
  3. Environments: Set for Production, Preview, and Development separately

Backend API (api.plings.io)

  1. Vercel Dashboard: Plings-API project → Settings → Environment Variables
  2. Variable Name: GATEWAY_API_KEY (canonical; DIRECTOR_API_KEY accepted as fallback)
  3. Default: the built-in development key applies only outside Vercel (local dev). In production, validation relies on the env var or the hashed key registry in app/gateway_auth.py.

Key Storage in Backend

The backend stores only the first 12 characters of the SHA256 hash of API keys:

import hashlib

def hash_api_key(api_key: str) -> str:
    """Hash an API key for storage/comparison."""
    return hashlib.sha256(api_key.encode()).hexdigest()[:12]

This ensures that even if the backend database is compromised, the actual API keys cannot be recovered.

Key Rotation Process

1. Generate New Key

NEW_KEY="gw_$(openssl rand -hex 32)"
echo "New API Key: $NEW_KEY"
echo "Hash for backend: $(echo -n $NEW_KEY | shasum -a 256 | cut -c1-12)"

2. Update Backend First

Add the new key hash to app/gateway_auth.py:

GATEWAY_API_KEYS = {
    "new_hash_here": {
        "name": "gateway-prod-vN",
        "created": "YYYY-MM-DD",
        "active": True
    },
    # Keep old key active during transition
    "old_hash_here": {
        "name": "gateway-prod-vN-1",
        "created": "YYYY-MM-DD",
        "active": True
    }
}

3. Deploy Backend

Deploy the backend with both keys active.

4. Update Gateway

Update the GATEWAY_API_KEY environment variable in Vercel (Plings-Gateway project) with the new key value.

5. Verify New Key

Test the Gateway service with the new key.

6. Deactivate Old Key

After verification, set the old key’s active to False in the backend.

Security Monitoring

What to Monitor

  1. Failed authentication attempts - Multiple failures may indicate attempted breach
  2. Unusual request patterns - Spike in requests or unusual times
  3. Geographic anomalies - Requests from unexpected locations
  4. Rate limit violations - May indicate abuse

Logging Requirements

All API key usage should be logged with:

Emergency Procedures

If a Key is Compromised

  1. Immediately deactivate the key in the backend
  2. Generate a new key using the secure methods above
  3. Update all services using the compromised key
  4. Review logs for unauthorized usage
  5. Notify security team and stakeholders

Backend Emergency Override

If all keys are compromised, the backend can be temporarily configured to reject all Gateway requests:

# In gateway_auth.py
EMERGENCY_LOCKDOWN = True  # Set via environment variable

Best Practices

  1. Environment-Specific Keys: Never use production keys in development
  2. Least Privilege: Each service should have only the permissions it needs
  3. Regular Audits: Review active keys quarterly
  4. Documentation: Keep a secure record of which keys are used where
  5. No Hardcoding: Always use environment variables

Compliance Notes