-
-
Notifications
You must be signed in to change notification settings - Fork 39.9k
Description
Summary *
With token-only gateway auth (no device identity), the Control UI connects and shows "Connected" / "Health OK", but Overview, Instances, Sessions, etc. all show "Error: missing scope: operator.read" and no data. The server accepts the connection but leaves scopes empty, so every operator method call fails.
Steps to reproduce *
1. Configure gateway with token auth (e.g. gateway.auth.mode: "token", gateway.auth.token set).
2. Allow Control UI without device (e.g. gateway.controlUi.dangerouslyDisableDeviceAuth: true or allowInsecureAuth).
3. Open Control UI in browser (e.g. http://<host>:18789), enter gateway token, click Connect.
4. Open Overview, then Instances or Sessions.
Expected behavior *
Overview and Instances/Sessions load and show gateway data (instances count, uptime, session list, etc.). No "missing scope: operator.read" errors once connected with valid token.
Actual behavior *
Dashboard shows "Connected" and "Health OK", but Overview, Instances, Sessions, and other tabs show "Error: missing scope: operator.read" and no data. Only the connection succeeds; all subsequent API calls that require operator.read fail.
OpenClaw version *
2026.2.14
Operating system *
Linux (Debian 6.1) / Docker
(Adjust if you use e.g. macOS/Windows.)
Install method
Docker (openclaw:skills), gateway on port 18789
Logs, screenshots, and evidence
Screenshot: Dashboard with "Connected", "Health OK", and red "Error: missing scope: operator.read" on Overview/Instances.
Root cause (from code): In src/gateway/server/ws-connection/message-handler.ts, when the client has no device identity, scopes are set to [] (line ~433). So token-only Control UI connections get no scopes and every operator.* method returns "missing scope: operator.read".
Impact and severity
Affected: Users running Control UI with token-only auth (e.g. over HTTP, or from another machine without device pairing).
Severity: Medium–high (dashboard is effectively read-only and shows no useful data despite "Connected").
Frequency: 100% when connecting with token only and no device identity.
Consequence: Cannot use dashboard to monitor instances, sessions, or cron; misleading "Health OK" suggests everything is fine.
Proposed fix
Idea: When the client is the Control UI, sends no device, and token/password auth succeeded (canSkipDevice), grant full operator scopes instead of []. Then the Control UI can call all operator methods with token-only auth.
File: src/gateway/server/ws-connection/message-handler.ts
Place: After the block that rejects with "device required" (after if (!canSkipDevice) { ... return; }), only when !device and canSkipDevice and isControlUi.
Code to add:
// Token-only control UI: grant full operator scopes so dashboard can read data
if (isControlUi && scopes.length === 0) {
scopes = [
"operator.read",
"operator.write",
"operator.admin",
"operator.approvals",
"operator.pairing",
];
connectParams.scopes = scopes;
}Security: Only clients that (1) identify as Control UI, (2) send no device, and (3) have already authenticated with the correct token/password get these scopes. Tested locally and in Docker; existing test "allows control ui without device identity when insecure auth is enabled" still passes. Happy to open a PR if this direction is wanted.
Additional information
Proposed fix (for maintainer feedback): When the client is Control UI, there is no device, and shared-secret auth succeeded (canSkipDevice), grant full operator scopes instead of leaving them empty. That way token-only dashboard connections can read/write like a device-paired UI. Change is ~10 lines in message-handler.ts; I tested it locally and the dashboard then loads all data. Existing test "allows control ui without device identity when insecure auth is enabled" still passes. Happy to open a PR if this direction is wanted.