Skip to main content

Authentication

ChatWalaʻau has two complementary auth mechanisms: a unified API key (Bearer token) and an optional web sign-in (username/password) for cloud deployments.

Unified API key

API_KEY is a single Bearer token that protects the external OpenAI API, every write REST endpoint, and the AG-UI chat stream when reached from a non-loopback (LAN) client. Same-machine clients (127.0.0.1, ::1, localhost) bypass auth, so localhost development stays zero-configuration even when APP_HOST=0.0.0.0.

API_KEY=sk-chatwalaau-your-secret-key-here
# APP_REQUIRE_AUTH_ON_LAN=true # default: fail-closed on LAN without a key

Decision matrix for write endpoints and the AG-UI chat stream (POST /ag-ui/):

Client addressAPP_REQUIRE_AUTH_ON_LANAPI_KEYOutcome
loopbackanyanyallow
LANfalseanyallow (operator opt-out)
LANtrueempty503
LANtruesetBearer required

/v1/responses always requires a matching Bearer key regardless of client address.

Upgrading from before v0.47.0

If APP_HOST is non-loopback and API_KEY is unset, the AG-UI stream now returns the same 503 / 401 as every other write endpoint. Add API_KEY=..., or accept LAN exposure explicitly with APP_REQUIRE_AUTH_ON_LAN=false.

Web SPA authentication (optional)

For deploying ChatWalaʻau as a private cloud web app where a single operator signs in through the browser. It coexists with API_KEY (still used for CLI / SDK access) and is disabled by default -- without AUTH_USERNAME there is no behavior change.

AUTH_USERNAME=admin
AUTH_PASSWORD_HASH=scrypt$N=16384,r=8,p=1$<base64-salt>$<base64-hash>
# AUTH_SESSION_TTL_SECONDS=86400 # default 24h, sliding
# AUTH_COOKIE_SECURE=auto # auto / true / false
# AUTH_COOKIE_NAME=chatwalaau_session

Generate the hash with the bundled CLI:

chatwalaau hash-password # interactive (confirms twice)
echo "$PASSWORD" | chatwalaau hash-password --stdin --quiet # scripted

When AUTH_USERNAME is set, the SPA renders a /login page; the server validates credentials in constant time and issues an opaque token via an HttpOnly + SameSite=Strict cookie. The backend then accepts either a Bearer API_KEY or a valid session cookie on every write endpoint and the AG-UI stream. The /v1/responses external-app path stays Bearer-only.

  • No new Python dependency (stdlib hashlib.scrypt + secrets)
  • Single-user model; process-local session store (restarts re-prompt)
  • HTTPS strongly recommended for non-loopback deployments
  • Loopback CLI calls keep their no-credential bypass