Skip to content

Latest commit

 

History

History
535 lines (380 loc) · 17.2 KB

SETUP.md

File metadata and controls

535 lines (380 loc) · 17.2 KB

Option A: Bot-Auth Proxy — Complete Setup Guide

What is this? A Go reverse proxy that sits in front of OpenClaw, authenticating every request through AuthSec before forwarding it to the OpenClaw Gateway. This gives you per-user identity, browser login, session management, multi-tenancy, and audit logging.


Table of Contents


Prerequisites

Requirement Version Notes
Docker + Docker Compose v2+ For containerized deployment
Go 1.22+ Only for local development
openssl Any For generating secrets
An AuthSec account — Sign up at authsec.ai
An OpenClaw instance — Either standalone or bundled via Docker Compose

How It Works

┌──────────┐                    ┌──────────────────────┐                     ┌─────────────────────┐
│  Client   │   HTTPS / WSS     │  bot-auth Proxy      │  internal network   │  OpenClaw Gateway   │
│           │ ────────────────→ │  (Go, port 8080)     │ ────────────────→   │  (port 18789)       │
│  Browser  │                   │                      │                     │                     │
│  CLI      │ ←────────────────│  Authenticates users  │  Injects gateway    │  Never exposed      │
│  API      │    Responses      │  via AuthSec JWT     │  token + user ID    │  to the public      │
└──────────┘                    └──────────────────────┘                     └─────────────────────┘

The proxy:

  1. Intercepts every inbound request
  2. Authenticates the user (session cookie or Bearer JWT)
  3. Authorizes via AuthSec permissions API (/uflow/user/permissions/check)
  4. Proxies the request to OpenClaw with the internal gateway token
  5. Never exposes the OpenClaw gateway token to clients

Step 1: Clone the Repository

git clone https://github.com/authsec-ai/authsec-openclaw.git
cd authsec-openclaw

Step 2: Get AuthSec Credentials

You need different credentials depending on which AuthSec mode you choose. There are three modes:

For authsec mode (Native — Recommended)

  1. Sign in to your AuthSec admin panel:

    https://<your-tenant>.app.authsec.ai/admin/login
    

    Example: https://package.app.authsec.ai/admin/login

  2. Navigate to Settings > API Keys (or Security > JWT)

  3. Copy these values:

    Value Where to Find It Environment Variable
    HS256 signing secret API Keys / JWT Settings AUTHSEC_JWT_SECRET
    Login page URL Your tenant login URL AUTHSEC_LOGIN_URL
    API base URL Your tenant's API base AUTHSEC_BASE_URL
    Admin email The email you used to sign up AUTHSEC_ADMIN_EMAIL

For sdk mode (OIDC)

  1. Create an OIDC client in your AuthSec dashboard
  2. Note the issuer URL, client ID, and client secret
  3. These map to AUTHSEC_ISSUER_URL, AUTHSEC_CLIENT_ID, AUTHSEC_CLIENT_SECRET

For stub mode (Development only)

No credentials needed. Uses a fake auth provider that accepts Bearer stub:email@example.com.


Step 3: Choose Your AuthSec Mode

Mode Use Case Auth Method Requirements
authsec Production with AuthSec native API HS256 JWT verification + permissions API JWT secret, base URL, login URL
sdk Production with OIDC provider Standard OIDC (discovery + JWKS) Issuer URL, client ID, client secret
stub Local development / testing Fake tokens (stub:email) Nothing

Step 4: Run with Docker Compose

This is the recommended way to run everything. Docker Compose starts both OpenClaw and the proxy.

4a. Configure the environment

cd deploy/docker-compose
cp .env .env.local

Edit .env.local with your values:

# ─── Required for all modes ───────────────────────────────────────
PROXY_PUBLIC_BASE_URL=http://localhost:8080
PROXY_HTTP_PORT=8080

# ─── OpenClaw connection (auto-configured in Docker Compose) ──────
OPENCLAW_UPSTREAM_URL=http://openclaw:18789
OPENCLAW_GATEWAY_TOKEN=<generate with: openssl rand -hex 32>
OPENCLAW_TRUSTED_PROXIES=172.20.0.0/16

# ─── Session security ─────────────────────────────────────────────
SESSION_HMAC_SECRET=<generate with: openssl rand -hex 32>

# ─── AuthSec mode ─────────────────────────────────────────────────
AUTHSEC_MODE=authsec

# ─── For AUTHSEC_MODE=authsec (native) ───────────────────────────
AUTHSEC_JWT_SECRET=<from AuthSec admin panel>
AUTHSEC_BASE_URL=https://package.app.authsec.ai
AUTHSEC_LOGIN_URL=https://package.app.authsec.ai/login
AUTHSEC_ADMIN_EMAIL=admin@example.com

# ─── For AUTHSEC_MODE=sdk (OIDC) ─────────────────────────────────
# AUTHSEC_ISSUER_URL=https://your-tenant.authsec.ai
# AUTHSEC_CLIENT_ID=your-client-id
# AUTHSEC_CLIENT_SECRET=your-client-secret
# AUTHSEC_AUDIENCE=

# ─── Logging ──────────────────────────────────────────────────────
LOG_LEVEL=info

4b. Generate secrets

# Generate both secrets in one go
echo "OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)"
echo "SESSION_HMAC_SECRET=$(openssl rand -hex 32)"

Copy the output into your .env.local file.

4c. Start the services

# HTTP only (development)
docker compose --env-file .env.local up --build

# With TLS via Caddy (production)
docker compose --env-file .env.local --profile tls up --build

# Detached mode
docker compose --env-file .env.local up --build -d

4d. What gets started

Service Port Description
openclaw 18789 (internal only) OpenClaw Gateway — NOT exposed to host
proxy 8080 (host) AuthSec proxy — the public entry point
caddy 80/443 (host) TLS termination (only with --profile tls)

Step 5: Run Locally (Development)

If you prefer to run the Go proxy directly on your machine:

5a. Start OpenClaw separately

# Option 1: Use Docker
docker run -d \
  -e OPENCLAW_GATEWAY_TOKEN=dev-token-change-me \
  -p 18789:18789 \
  ghcr.io/openclaw/openclaw:latest

# Option 2: Use the OpenClaw CLI
openclaw gateway --bind loopback --port 18789

5b. Set environment variables

export AUTHSEC_MODE=stub          # Use stub for quick dev
export OPENCLAW_UPSTREAM_URL=http://localhost:18789
export OPENCLAW_GATEWAY_TOKEN=dev-token-change-me
export PROXY_PUBLIC_BASE_URL=http://localhost:8080
export SESSION_HMAC_SECRET=$(openssl rand -hex 32)
export STUB_ALLOWLIST=you@example.com

5c. Build and run

# Build
go build ./cmd/authsec-openclaw-proxy

# Run
./authsec-openclaw-proxy

# Or run directly
go run ./cmd/authsec-openclaw-proxy

5d. Test with stub mode

# Health check
curl http://localhost:8080/healthz

# Authenticated request (stub mode)
curl -H "Authorization: Bearer stub:you@example.com" http://localhost:8080/

# Browser login
open http://localhost:8080

Step 6: Run with the Startup Script

The scripts/start-authsec.sh script automates the setup for authsec native mode:

# Set the two required values
export AUTHSEC_JWT_SECRET=<from-admin-panel>
export AUTHSEC_LOGIN_URL=https://package.app.authsec.ai/login

# Run with Docker Compose (default)
./scripts/start-authsec.sh docker

# Or run the proxy locally (you start OpenClaw separately)
./scripts/start-authsec.sh local

# Or just print the env vars for manual use
./scripts/start-authsec.sh env

The script automatically:

  • Generates OPENCLAW_GATEWAY_TOKEN if not set
  • Generates SESSION_HMAC_SECRET if not set
  • Sets AUTHSEC_BASE_URL to https://package.app.authsec.ai
  • Sets AUTHSEC_ADMIN_EMAIL to the default admin email
  • Validates that required secrets are present
  • Writes a .env.authsec file for Docker Compose
  • Starts the full stack

Step 7: Verify Everything Works

Health checks

# Proxy health
curl http://localhost:8080/healthz
# Expected: 200 OK

# Ready check
curl http://localhost:8080/readyz
# Expected: 200 OK

Browser login flow

  1. Open http://localhost:8080 in a browser
  2. You should be redirected to the AuthSec login page
  3. After authenticating, you're redirected back with a session cookie
  4. Subsequent requests use the session cookie

API access with JWT

# With a real AuthSec JWT
curl -H "Authorization: Bearer <your-jwt>" http://localhost:8080/

# With stub mode
curl -H "Authorization: Bearer stub:admin@example.com" http://localhost:8080/

Check logs

# Docker Compose
docker compose logs -f proxy

# Local
# Logs print to stdout in JSON format

Step 8: Connect Clients

OpenClaw CLI

# Using the authsec-openclaw-cli
./authsec-openclaw-cli login --proxy-url http://localhost:8080
./authsec-openclaw-cli run-tui

# Or configure OpenClaw CLI directly to connect through the proxy
openclaw connect --remote-url ws://localhost:8080 --remote-token <your-jwt>

API clients

# Any HTTP client with Bearer token
curl -H "Authorization: Bearer <jwt>" http://localhost:8080/api/v1/chat

# WebSocket connection
wscat -c ws://localhost:8080/ws -H "Authorization: Bearer <jwt>"

Browser

Navigate to http://localhost:8080. The proxy handles the login redirect flow automatically.


Environment Variable Reference

Core Configuration

Variable Required Default Description
PROXY_PUBLIC_BASE_URL Yes — Public URL of the proxy (for OAuth redirects)
LISTEN_ADDR No :8080 Address the proxy listens on
OPENCLAW_UPSTREAM_URL No http://openclaw:18789 OpenClaw Gateway URL
OPENCLAW_GATEWAY_TOKEN Yes — Shared token for OpenClaw Gateway
SESSION_HMAC_SECRET Yes — HMAC key for session cookies (min 32 chars)
SESSION_COOKIE_NAME No oc_session Session cookie name
SESSION_TTL No 8h Session lifetime
SESSION_SECURE_COOKIE No true Set false for HTTP (dev only)
LOG_LEVEL No info Log level

AuthSec Configuration

Variable Mode Required Default Description
AUTHSEC_MODE All No sdk Auth mode: authsec, sdk, or stub
AUTHSEC_JWT_SECRET authsec Yes — HS256 signing key for JWT verification
AUTHSEC_BASE_URL authsec Yes — AuthSec API base URL
AUTHSEC_LOGIN_URL authsec Yes — AuthSec web login page URL
AUTHSEC_ISSUER_URL sdk Yes — OIDC issuer URL
AUTHSEC_CLIENT_ID sdk Yes — OIDC client ID
AUTHSEC_CLIENT_SECRET sdk Yes — OIDC client secret
AUTHSEC_AUDIENCE Both No — JWT audience claim
AUTHSEC_ADMIN_EMAIL Both No — Admin email (bypasses authorization)
AUTHSEC_ADMIN_SUB Both No — Admin subject (bypasses authorization)
AUTHSEC_REQUIRED_CLAIM Both No — Required claim (e.g. groups:openclaw)
AUTHSEC_SCOPES sdk No openid,profile,email OIDC scopes

Security Configuration

Variable Required Default Description
RATE_LIMIT_PER_MINUTE No 10 Auth endpoint rate limit per IP
MAX_REQUEST_BODY_BYTES No 1048576 Max request body size (1MB)
TRUSTED_PROXY_IPS No — Comma-separated trusted proxy IPs

Multi-Tenant Configuration

Variable Required Default Description
TENANT_ROUTING_MODE No host host or path
TENANT_DEFAULT No — Default tenant ID
TENANT_CONFIG_JSON No — JSON map of tenant configs

AuthSec Mode Comparison

authsec (Native) — Recommended for AuthSec Users

Client → Proxy → [HS256 JWT verify locally] → [AuthSec permissions API] → OpenClaw
  • Verifies JWT signatures locally (fast, no round-trip for validation)
  • Calls AuthSec API only for authorization decisions
  • Supports browser login with redirect flow
  • Requires: AUTHSEC_JWT_SECRET, AUTHSEC_BASE_URL, AUTHSEC_LOGIN_URL

sdk (OIDC) — For Standard OIDC Providers

Client → Proxy → [OIDC discovery + JWKS verify] → OpenClaw
  • Standard OIDC flow (works with any OIDC provider)
  • Full OIDC discovery (.well-known/openid-configuration)
  • Supports device-code flow for CLI
  • Requires: AUTHSEC_ISSUER_URL, AUTHSEC_CLIENT_ID, AUTHSEC_CLIENT_SECRET

stub — Development Only

Client → Proxy → [Accept any "stub:email" token] → OpenClaw
  • No real authentication — accepts Bearer stub:email@example.com
  • Optional allowlist via STUB_ALLOWLIST
  • Never use in production

Multi-Tenant Setup

Host-based routing

export TENANT_ROUTING_MODE=host
export TENANT_CONFIG_JSON='{
  "acme": {
    "upstream_url": "http://openclaw-acme:18789",
    "gateway_token": "token-for-acme"
  },
  "globex": {
    "upstream_url": "http://openclaw-globex:18789",
    "gateway_token": "token-for-globex"
  }
}'

Requests to acme.proxy.example.com route to the acme OpenClaw instance.

Path-based routing

export TENANT_ROUTING_MODE=path
# Same TENANT_CONFIG_JSON as above

Requests to proxy.example.com/acme/... route to the acme OpenClaw instance.


Production Deployment

Checklist

  • Set AUTHSEC_MODE=authsec or AUTHSEC_MODE=sdk
  • Generate strong secrets: openssl rand -hex 32 for each
  • Set SESSION_SECURE_COOKIE=true
  • Enable TLS (Caddy profile or external load balancer)
  • Set PROXY_PUBLIC_BASE_URL to your real domain (e.g., https://openclaw.company.com)
  • Set AUTHSEC_ADMIN_EMAIL to the admin's real email
  • Verify OpenClaw Gateway is NOT exposed to the public network
  • Review rate limiting (RATE_LIMIT_PER_MINUTE)
  • Consider multi-tenant setup if serving multiple organizations

Docker Compose with TLS

cd deploy/docker-compose

# Edit Caddyfile with your domain
# Edit .env.local with production values

docker compose --env-file .env.local --profile tls up -d

Kubernetes

See deploy/helm/authsec-openclaw/README.md for Helm chart deployment.


Troubleshooting

"config: AUTHSEC_JWT_SECRET is required when AUTHSEC_MODE=authsec"

You're running in authsec mode but haven't set the JWT signing secret. Get it from your AuthSec admin panel (Settings > API Keys).

"config: OPENCLAW_GATEWAY_TOKEN is required"

Generate one: openssl rand -hex 32. This is the shared secret between the proxy and OpenClaw — it is NOT the user's JWT.

"config: SESSION_HMAC_SECRET must be at least 32 characters"

Generate one: openssl rand -hex 32. This signs session cookies.

Proxy starts but OpenClaw is unreachable

  • Check that OPENCLAW_UPSTREAM_URL matches OpenClaw's actual address
  • In Docker Compose, use the service name: http://openclaw:18789
  • Locally, use: http://localhost:18789

"authsec native: verify JWT signature: signature verification failed"

The AUTHSEC_JWT_SECRET doesn't match the key that signed the JWT. Verify you copied the correct signing key from the AuthSec admin panel.

"authsec native: token validation: token is expired"

The JWT has expired. The user needs to re-authenticate to get a fresh token.

Browser login redirects in a loop

  • Check that PROXY_PUBLIC_BASE_URL matches the actual URL you're accessing
  • Check that AUTHSEC_LOGIN_URL is correct
  • Check that SESSION_SECURE_COOKIE=false if you're using HTTP (dev only)

Rate limited (429)

The default rate limit is 10 requests per minute per IP on auth endpoints. Adjust with RATE_LIMIT_PER_MINUTE.