Authentication

How Backstop's bearer token authentication works, token scopes, and how to configure multi-token setups for different agents and operators.

The Backstop gateway uses bearer token authentication. All requests (except /health) require an Authorization header.

Bearer token

Authorization: Bearer <token>

Tokens are defined in a JSON file and passed to the gateway at startup:

BACKSTOP_TOKENS=/etc/backstop/tokens.json backstop-gateway

Token file format

[
  {
    "id": "agent-prod-01",
    "token": "bsp_prod_xxxxxxxxxxxxxxxxxxxxxx",
    "scopes": ["query:execute", "query:analyze", "metadata:read"],
    "description": "Production agent — cursor-pratyush"
  },
  {
    "id": "operator-01",
    "token": "bsp_ops_xxxxxxxxxxxxxxxxxxxxxx",
    "scopes": ["approval:read", "approval:write", "metadata:read"],
    "description": "Operator — PagerDuty webhook"
  },
  {
    "id": "prometheus",
    "token": "bsp_prom_xxxxxxxxxxxxxxxxxxxxxx",
    "scopes": ["metrics:read"],
    "description": "Prometheus scrape"
  },
  {
    "id": "admin",
    "token": "bsp_admin_xxxxxxxxxxxxxxxxxxxxxx",
    "scopes": ["admin:*", "query:execute", "query:analyze", "approval:read", "approval:write", "metadata:read", "metrics:read"],
    "description": "Emergency admin — break-glass only"
  }
]

Scopes reference

ScopeAccess granted
query:executeexecute_query tool — run SQL through the gateway
query:analyzeanalyze_query tool — classify without executing
approval:readGET /pending — list pending approvals
approval:writePOST /approve/{id}, POST /deny/{id}
metadata:read/metadata/snapshots, /metadata/audit, /metadata/alerts, /metadata/health
metrics:readGET /metrics — Prometheus endpoint
admin:*All admin endpoints: /admin/pause, /admin/resume, /admin/status

Token generation

Generate cryptographically random tokens:

# macOS / Linux
openssl rand -hex 32

# Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Python
python3 -c "import secrets; print(secrets.token_hex(32))"

Error responses

HTTP statusMeaning
401 UnauthorizedMissing or invalid token
403 ForbiddenToken valid but lacks required scope
{
  "error": "insufficient_scope",
  "message": "Token does not have approval:write scope",
  "required_scope": "approval:write"
}

Development token

The default development token is dev-token with full access. It is only active when BACKSTOP_DEV_MODE=true is set. Never use in production.