mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-21 21:15:09 +00:00
feat(server): anonymous key allowlist for multi-mode (v3.7.0) (#15)
Implements issue #12 section 14 Path A. Lets OCP admin designate a single well-known "anonymous" key that bypasses validateKey() while keeping AUTH_MODE=multi. Gives OpenClaw multi-agent clients (which MUST send a non-empty Authorization header per their per-agent auth-profiles schema) a way to connect without every user needing a personal key. ## Background After PR-1 (issue #12), we know OpenClaw multi-agent setups require a per-agent auth-profiles.json with a non-empty `key` field. OCP multi-mode rejects any non-empty Bearer token that isn't in the keys database (server.mjs line 1152), which creates a deadlock: the only way for OpenClaw to use OCP is with a real admin-issued key. Path A resolves this by letting the admin opt in to a public anonymous key that clients can auto-discover via /health. OpenClaw writes this key into its agent profiles just like a real key; OCP server short-circuits validateKey when the key matches the allowlist. No per-user coordination needed, admin still controls the policy (can rotate, can unset, can rate-limit). ## Changes ### server.mjs * Line 100-103: new `PROXY_ANONYMOUS_KEY` env var + warning if set while AUTH_MODE is not multi. * Line 1127-1138 (localhost branch): anonymous allowlist short-circuit before validateKey so localhost clients using the anon key are labeled "anonymous" instead of "local" in stats. * Line 1153-1163 (multi branch): the same allowlist check between the ADMIN_KEY check and validateKey. Uses timingSafeEqual with explicit length check (consistent with the admin and shared key patterns above). * Line 1221 (/health response): new `anonymousKey` field, null when not set, the actual value when set. Admins opted into public access when they set the env var, so exposing the key here is intentional and lets ocp-connect auto-discover it without out-of-band coordination. ### package.json Version 3.6.0 to 3.7.0 (per dev iron rule 5, version bump before push). ### README.md New "Anonymous Access (optional)" subsection under Auth Modes: * Enable example (export PROXY_ANONYMOUS_KEY=...) * Client-side /health discovery explanation * Security note: opt-in to public access, rate-limit warning * "Not a secret" note: /health is unauthenticated, the key is publicly readable by design; treat it as a convenience handle, not as an access credential. ## Test evidence Offline tests on macOS 13, local server on 0.0.0.0:8889 with PROXY_ANONYMOUS_KEY=ocp_public_anon_TEST, CLAUDE_AUTH_MODE=multi, CLAUDE=/bin/echo (mock): * GET /health -> authMode: multi anonymousKey: ocp_public_anon_TEST (pass, field exposed correctly) * POST /v1/chat/completions with Bearer ocp_WRONG_KEY from 172.16.2.29 (non-localhost) -> HTTP 401 in 15ms body: Unauthorized: invalid or revoked API key (pass, validateKey still rejects unknown keys) * POST /v1/chat/completions with Bearer ocp_public_anon_TEST from 172.16.2.29 -> curl hangs at 3s after auth middleware (pass, auth passed, request reached Claude handler which hangs because CLAUDE=/bin/echo cant serve a real chat; the point is the auth middleware accepted the key, confirmed by no 401 return) * POST /v1/chat/completions with no Authorization from 172.16.2.29 -> curl hangs at 3s after auth middleware (pass, pre-existing empty-token anonymous path not regressed) node --check server.mjs: syntax OK. ## Code review One independent opus reviewer. Verdict: PASS WITH CONCERNS, zero blockers. Two strong-recommend items addressed in this commit: 1. Localhost branch was not covered in the first draft. Reviewer pointed out that a localhost client using the anon key would be labeled "local" instead of "anonymous" in stats, making operations visibility worse. Fixed by applying the same anonymous allowlist check in the localhost branch at line 1127-1138. 2. README security note was missing the explicit "not a secret" framing. Added a paragraph clarifying that because /health is unauthenticated, the anonymous key is publicly readable by anyone who can reach the server, which is intentional. Reviewer nits (tokenBuf3 naming, stats subcategory for header-less vs anon-key anonymous) are deferred as they do not affect correctness. ## Upstream dependencies on this commit After this PR is merged and the OCP instance at 172.16.2.30 is restarted with `PROXY_ANONYMOUS_KEY` set in the environment, a follow-up PR can add anonymous key auto-discovery to ocp-connect: * On startup, ocp-connect calls GET /health * If anonymousKey field is non-null and --key was not provided, ocp-connect automatically uses that key to seed per-agent auth-profiles for OpenClaw * User gets zero-config OCP connectivity for OpenClaw multi-agent setups, no admin coordination, no --key flag That follow-up is NOT in this PR. This PR is server-only. Co-authored-by: taodeng <taodeng@Taos-MBP> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
taodeng
Claude Opus 4.6
parent
2adea6368d
commit
38070fbabb
@@ -222,6 +222,23 @@ ocp keys revoke son-ipad # Revoke a key
|
||||
| `shared` | `CLAUDE_AUTH_MODE=shared` + `PROXY_API_KEY=xxx` | Everyone shares one key |
|
||||
| `multi` | `CLAUDE_AUTH_MODE=multi` + `OCP_ADMIN_KEY=xxx` | Per-person keys with usage tracking (recommended) |
|
||||
|
||||
### Anonymous Access (optional)
|
||||
|
||||
In `multi` mode, the admin can designate a single well-known "anonymous" key that bypasses `validateKey()` and grants public read/write access. This is useful for letting LAN users (or clients like OpenClaw multi-agent setups) connect without individual per-user keys.
|
||||
|
||||
**Enable**:
|
||||
|
||||
```bash
|
||||
export PROXY_ANONYMOUS_KEY=ocp_public_anon # or any string of your choice
|
||||
ocp start # or however you start the server
|
||||
```
|
||||
|
||||
**Client side**: the anonymous key value is exposed via `GET /health` as the field `anonymousKey` (null when not set). Clients like `ocp-connect` can auto-discover and use it, so the end user doesn't need to get a personal key from the admin.
|
||||
|
||||
**Security note**: setting this env var is an **opt-in** to public access — anyone who can reach your OCP endpoint can use it, up to any rate limits you configure. Don't enable this on internet-exposed OCP instances without additional protection.
|
||||
|
||||
**Not a secret**: because `/health` is an unauthenticated endpoint, the anonymous key is **publicly readable** by anyone who can reach the server. That is intentional — the key exists so clients can self-configure without out-of-band coordination. Treat it as a convenience handle, not as an access credential.
|
||||
|
||||
### Important Notes
|
||||
|
||||
- All users share your Claude Pro/Max **rate limits** (5h session + 7d weekly)
|
||||
|
||||
Reference in New Issue
Block a user