API Authentication

The Opta stack uses different authentication mechanisms at each layer -- Bearer tokens for the daemon, admin keys for LMX, environment variables or Keychain for API keys, and Supabase JWTs for cloud-enabled web apps.

Authentication Overview

ServiceAuth MethodStorage
Daemon (HTTP)Bearer tokenstate.json
Daemon (WebSocket)Query parameterstate.json
LMX (admin)Admin keymacOS Keychain
LMX (inference)None (open)N/A
Anthropic CloudAPI keyEnv var or Keychain
Cloud Web AppsSupabase JWTSecure cookie

Daemon Authentication

Bearer Token (HTTP)

All HTTP requests to the daemon require a Bearer token in the Authorization header. The token is generated when the daemon starts and stored in the state file.

Authenticated daemon request
# Read the token from state.json
TOKEN=$(jq -r .token ~/.config/opta/daemon/state.json)

# Use it in API requests
curl -s http://127.0.0.1:9999/v3/sessions \
  -H "Authorization: Bearer $TOKEN"

The daemon validates tokens using crypto.timingSafeEqual to prevent timing-based attacks that could be used to incrementally guess the token value.

Query Parameter (WebSocket)

WebSocket connections cannot send custom headers during the handshake. Instead, the token is passed as a query parameter:

WebSocket authentication
// Token in query parameter for WebSocket
const ws = new WebSocket(
  "ws://127.0.0.1:9999/v3/events?token=<token>"
);
Query parameter safety
The WebSocket connection runs over localhost only, so the token in the query string is not exposed to network intermediaries. On production deployments with TLS, consider using a secure WebSocket (wss://) connection.

Token Rotation

The daemon generates a new token every time it starts. This means:

  • Restarting the daemon invalidates all existing tokens immediately
  • Clients must read the new token from state.json after a restart
  • Code Desktop handles this automatically by detecting auth failures and refreshing the stored token
  • Compromised tokens have a limited window of validity (until the next restart)

LMX Admin Key

LMX inference endpoints (like /v1/chat/completions) are open and do not require authentication. This allows any client on the LAN to send inference requests.

Administrative endpoints (model loading, unloading, server configuration) require an admin key. This key is stored in the macOS Keychain on the machine running LMX.

The admin key is set during LMX installation and stored in the macOS Keychain. To update it:

security add-generic-password \
  -s "opta-lmx" -a "admin" \
  -w "<new-key>" -U

Anthropic API Key

If you configure the CLI to use Anthropic's cloud API as a fallback or primary provider, you need an Anthropic API key. The key can be stored in two locations:

  • Environment variable -- ANTHROPIC_API_KEY in your shell environment
  • macOS Keychain -- stored securely via opta key set anthropic

The Keychain option is recommended as it keeps the key out of shell history, dotfiles, and environment variable listings.

Storing an Anthropic API key
# Store in Keychain (recommended)
opta key set anthropic

# Or set as environment variable
export ANTHROPIC_API_KEY="sk-ant-..."

Supabase JWT

Cloud-enabled Opta web apps (Local Web in WAN mode, Opta Accounts) use Supabase authentication. After signing in, the user receives a JWT that is stored in a secure HTTP-only cookie.

The JWT is verified by Supabase middleware on every request. All Opta apps share a single Supabase project, so one sign-in grants access to all cloud-enabled services.

The Supabase SSR pattern used across Opta web apps splits auth into three concerns:

  • Client -- reads the session from cookies in the browser
  • Server -- validates the session on server-rendered pages
  • Middleware -- refreshes tokens and protects routes
Cloud auth is opt-in
Supabase authentication is only used when apps are accessed through a Cloudflare Tunnel. On LAN, no auth is required and no Supabase configuration is needed.