From ebe0a27b4d84ebd06fc58e85e8d88610320c2db8 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 4 Apr 2026 14:23:26 +0100 Subject: [PATCH] docs: refresh device token scope refs --- docs/cli/devices.md | 3 +++ docs/gateway/protocol.md | 7 +++++++ docs/gateway/troubleshooting.md | 3 +++ docs/help/faq.md | 1 + docs/help/troubleshooting.md | 3 +++ 5 files changed, 17 insertions(+) diff --git a/docs/cli/devices.md b/docs/cli/devices.md index 81f5f7488df..0d3de57e676 100644 --- a/docs/cli/devices.md +++ b/docs/cli/devices.md @@ -72,6 +72,9 @@ openclaw devices reject Rotate a device token for a specific role (optionally updating scopes). The target role must already exist in that device's approved pairing contract; rotation cannot mint a new unapproved role. +If you omit `--scope`, later reconnects with the stored rotated token reuse that +token's cached approved scopes. If you pass explicit `--scope` values, those +become the stored scope set for future cached-token reconnects. ``` openclaw devices rotate --device --role operator --scope operator.read --scope operator.write diff --git a/docs/gateway/protocol.md b/docs/gateway/protocol.md index 58c8a650818..4691ce07096 100644 --- a/docs/gateway/protocol.md +++ b/docs/gateway/protocol.md @@ -273,9 +273,16 @@ The Gateway treats these as **claims** and enforces server-side allowlists. persisted by the client for future connects. - Clients should persist the primary `hello-ok.auth.deviceToken` after any successful connect. +- Reconnecting with that **stored** device token should also reuse the stored + approved scope set for that token. This preserves read/probe/status access + that was already granted and avoids silently collapsing reconnects to a + narrower implicit admin-only scope. - Additional `hello-ok.auth.deviceTokens` entries are bootstrap handoff tokens. Persist them only when the connect used bootstrap auth on a trusted transport such as `wss://` or loopback/local pairing. +- If a client supplies an **explicit** `deviceToken` or explicit `scopes`, that + caller-requested scope set remains authoritative; cached scopes are only + reused when the client is reusing the stored per-device token. - Device tokens can be rotated/revoked via `device.token.rotate` and `device.token.revoke` (requires `operator.pairing` scope). - Token issuance/rotation stays bounded to the approved role set recorded in diff --git a/docs/gateway/troubleshooting.md b/docs/gateway/troubleshooting.md index a86af2000e3..0d26534cdce 100644 --- a/docs/gateway/troubleshooting.md +++ b/docs/gateway/troubleshooting.md @@ -117,6 +117,9 @@ Common signatures: - `device signature invalid` / `device signature expired` → client signed the wrong payload (or stale timestamp) for the current handshake. - `AUTH_TOKEN_MISMATCH` with `canRetryWithDeviceToken=true` → client can do one trusted retry with cached device token. +- That cached-token retry reuses the cached scope set stored with the paired + device token. Explicit `deviceToken` / explicit `scopes` callers keep their + requested scope set instead. - `too many failed authentication attempts (retry later)` from a browser-origin loopback client → repeated failures from that same normalized `Origin` are locked out temporarily; another localhost origin uses a separate bucket. diff --git a/docs/help/faq.md b/docs/help/faq.md index b1d75266f81..83550e310d8 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -2552,6 +2552,7 @@ Related: [/concepts/oauth](/concepts/oauth) (OAuth flows, token storage, multi-a - The Control UI keeps the token in `sessionStorage` for the current browser tab session and selected gateway URL, so same-tab refreshes keep working without restoring long-lived localStorage token persistence. - On `AUTH_TOKEN_MISMATCH`, trusted clients can attempt one bounded retry with a cached device token when the gateway returns retry hints (`canRetryWithDeviceToken=true`, `recommendedNextStep=retry_with_device_token`). + - That cached-token retry now reuses the cached approved scopes stored with the device token. Explicit `deviceToken` / explicit `scopes` callers still keep their requested scope set instead of inheriting cached scopes. Fix: diff --git a/docs/help/troubleshooting.md b/docs/help/troubleshooting.md index 7e05647b7f4..e9cdfbe6231 100644 --- a/docs/help/troubleshooting.md +++ b/docs/help/troubleshooting.md @@ -139,6 +139,9 @@ flowchart TD - `origin not allowed` → browser `Origin` is not allowed for the Control UI gateway target. - `AUTH_TOKEN_MISMATCH` with retry hints (`canRetryWithDeviceToken=true`) → one trusted device-token retry may occur automatically. + - That cached-token retry reuses the cached scope set stored with the paired + device token. Explicit `deviceToken` / explicit `scopes` callers keep + their requested scope set instead. - `too many failed authentication attempts (retry later)` from a localhost browser origin → repeated failures from that same `Origin` are temporarily locked out; another localhost origin uses a separate bucket.