From 7d09ff89ee3a8a517bdac75d704d1770a3a2bf78 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 17 May 2026 02:24:03 +0800 Subject: [PATCH] fix(gateway): honor env token for remote interactive auth --- CHANGELOG.md | 1 + src/gateway/auth-surface-resolution.test.ts | 67 +++++++++++++++++++++ src/gateway/auth-surface-resolution.ts | 2 +- 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/gateway/auth-surface-resolution.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f6c8ac0700..6683b9a8b56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Docs: https://docs.openclaw.ai - CLI/config: add `--dry-run` support to `openclaw config unset`, with `--json` output and allow-exec validation parity with `config set`/`config patch` dry-run handling. (#81895) Thanks @giodl73-repo. - Memory-core: retry disabled dreaming cron cleanup until cron is available after startup, so persisted managed dreaming jobs are removed after restart. Fixes #82383. (#82389) Thanks @neeravmakwana. - Gateway/diagnostics: redact credential-bearing gateway target URLs and client diagnostics while preserving raw connection URLs for programmatic use, so connect-failure logs no longer surface embedded tokens. +- Gateway/auth: honor `OPENCLAW_GATEWAY_TOKEN` as the remote interactive fallback when no remote token is configured, keeping remote TUI setup aligned with documented auth precedence. - Logs: redact raw Basic auth and named security headers from `logs.tail` output before returning lines to read-scoped clients. Fixes #66832. Thanks @Magicray1217. - CLI/gateway: emit structured JSON for gateway transport close/timeout failures when `--json` is requested by health, gateway health, and devices list commands. Fixes #79108. Thanks @TurboTheTurtle. - Telegram: normalize announce group targets via a new `resolveSessionTarget` channel hook so scheduled announcements resolve consistently against the same Telegram session conversation registry as inbound turns. Fixes #81229. Thanks @giodl73-repo. diff --git a/src/gateway/auth-surface-resolution.test.ts b/src/gateway/auth-surface-resolution.test.ts new file mode 100644 index 00000000000..508197b6e42 --- /dev/null +++ b/src/gateway/auth-surface-resolution.test.ts @@ -0,0 +1,67 @@ +import { describe, expect, it } from "vitest"; +import type { GatewayRemoteConfig } from "../config/types.gateway.js"; +import type { OpenClawConfig } from "../config/types.openclaw.js"; +import { resolveGatewayInteractiveSurfaceAuth } from "./auth-surface-resolution.js"; + +function remoteGatewayConfig(remote?: GatewayRemoteConfig): OpenClawConfig { + return { + gateway: { + mode: "remote", + remote: { + url: "wss://remote.example/ws", + ...remote, + }, + }, + }; +} + +describe("resolveGatewayInteractiveSurfaceAuth", () => { + it("uses OPENCLAW_GATEWAY_TOKEN as remote interactive fallback", async () => { + await expect( + resolveGatewayInteractiveSurfaceAuth({ + config: remoteGatewayConfig(), + env: { + OPENCLAW_GATEWAY_TOKEN: "env-token", + }, + surface: "remote", + }), + ).resolves.toEqual({ + token: "env-token", + password: undefined, + }); + }); + + it("keeps configured remote token ahead of OPENCLAW_GATEWAY_TOKEN", async () => { + await expect( + resolveGatewayInteractiveSurfaceAuth({ + config: remoteGatewayConfig({ token: "remote-token" }), + env: { + OPENCLAW_GATEWAY_TOKEN: "env-token", + }, + surface: "remote", + }), + ).resolves.toEqual({ + token: "remote-token", + password: undefined, + }); + }); + + it("falls back to OPENCLAW_GATEWAY_TOKEN when the remote token ref is unresolved", async () => { + await expect( + resolveGatewayInteractiveSurfaceAuth({ + config: { + ...remoteGatewayConfig({ + token: { source: "env", provider: "default", id: "MISSING_REMOTE_TOKEN" }, + }), + }, + env: { + OPENCLAW_GATEWAY_TOKEN: "env-token", + }, + surface: "remote", + }), + ).resolves.toEqual({ + token: "env-token", + password: undefined, + }); + }); +}); diff --git a/src/gateway/auth-surface-resolution.ts b/src/gateway/auth-surface-resolution.ts index 2154ee3be7f..058f3122d53 100644 --- a/src/gateway/auth-surface-resolution.ts +++ b/src/gateway/auth-surface-resolution.ts @@ -183,7 +183,7 @@ export async function resolveGatewayInteractiveSurfaceAuth(params: { path: "gateway.remote.password", value: params.config.gateway?.remote?.password, }); - const token = explicitToken ?? remoteToken.value; + const token = explicitToken ?? remoteToken.value ?? envToken; const password = explicitPassword ?? envPassword ?? remotePassword.value; return token || password ? { token, password }