Skip to content

[Bug]: Dashboard shows "Connected" and "Health OK" but "Error: missing scope: operator.read" - no data with token-only auth #17095

@Al3xand3r1987

Description

@Al3xand3r1987

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions