fix(gateway): include device token for fallback auth when shared token is configured#39002
Conversation
…n is configured When gateway.auth.token is manually configured in openclaw.json, the client was not including the device token in auth.deviceToken for the server to use as a fallback. This caused authentication failures with 'token_mismatch' errors because: 1. User configures gateway.auth.token in openclaw.json 2. User pairs CLI device (openclaw pair) → device gets unique token in paired.json 3. CLI sends the configured gateway.auth.token, but this mismatches the paired device token stored on the server 4. Server cannot fall back to device token verification because auth.deviceToken was undefined The fix ensures the stored device token is always included in auth.deviceToken, allowing the server to use device-token authentication as a fallback when shared token auth fails. Fixes openclaw#38617
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 Stored per-device token is always sent in connect auth payload (token exfiltration to untrusted gateway URL)
DescriptionThe Gateway client now always includes a locally persisted per-device token ( This is a security regression because it unnecessarily discloses a long-lived bearer credential to whatever URL the client is configured to connect to:
Vulnerable code: const storedToken = this.opts.deviceIdentity
? loadDeviceAuthToken({ deviceId: this.opts.deviceIdentity.deviceId, role })?.token
: null;
// Always include the device token when available.
const resolvedDeviceToken = explicitDeviceToken ?? storedToken ?? undefined;
...
const auth = authToken || authPassword || resolvedDeviceToken
? { token: authToken, deviceToken: resolvedDeviceToken, password: authPassword }
: undefined;Note: While the client blocks plaintext RecommendationAvoid sending a persisted per-device token unless it is strictly required and/or the destination is explicitly trusted. Mitigation options (choose one or combine):
const resolvedDeviceToken =
explicitDeviceToken ?? (!explicitGatewayToken && !authPassword ? (storedToken ?? undefined) : undefined);
Additionally, consider an explicit option like Analyzed PR: #39002 at commit Last updated on: 2026-03-07T17:12:39Z |
Greptile SummaryThis PR fixes a bug where paired CLI devices could not authenticate against a gateway with a manually configured The one-line change to Confidence Score: 4/5
Last reviewed commit: e35114c |
|
Thanks for the contribution here. We merged #42507, which supersedes this PR with a broader implementation: bounded trusted retry, reconnect-loop gating, protocol recovery hints, cross-client alignment, regression coverage, and docs/runbook updates. Closing this PR as superseded by the merged follow-up. |
Problem
When
gateway.auth.tokenis manually configured inopenclaw.json, the CLI cannot connect to the Gateway withtoken_mismatcherror, even though the device was successfully paired viaopenclaw pair.Root Cause: The client was excluding the stored device token from
auth.deviceTokenwhen an explicit shared token was provided. This prevented the server from falling back to device-token authentication when shared token validation failed.Impact: Paired CLI devices cannot authenticate when
gateway.auth.tokenis manually configured, breaking all CLI commands.Root Cause
In
src/gateway/client.ts, theresolvedDeviceTokenwas set toundefinedwhenexplicitGatewayTokenwas present:This meant
auth.deviceTokenwas never sent to the server when a shared token was configured, so the server couldn't use device-token auth as a fallback.Fix
Always include the stored device token when available:
The server already supports using
auth.deviceTokenas a fallback whenauth.tokenfails shared auth validation. This fix ensures the client sends both tokens, allowing the server to authenticate via the device token when the shared token doesn't match.Testing
pnpm test -- src/gateway/client.test.ts src/gateway/auth.test.ts src/gateway/server/ws-connection/auth-context.test.ts)Fixes #38617
@greptile-apps please review