fix(gateway): add shared-secret fallback to trusted-proxy auth dispatcher#17746
fix(gateway): add shared-secret fallback to trusted-proxy auth dispatcher#17746dashed wants to merge 3 commits intoopenclaw:mainfrom
Conversation
4a7e7c7 to
fa317c8
Compare
4080fab to
33697e5
Compare
8e9101d to
be6e6df
Compare
|
Note on Windows CI failure: The The test `passes manager-scoped XDG env to mcporter commands` in `src/memory/qmd-manager.test.ts` (introduced by #19617 / commit 3317b49) uses hardcoded Unix forward slashes in path assertions that fail on Windows. Main's own CI run 22268115588 shows the same failure. Fix PR: #23128 |
4a9e169 to
4647d8a
Compare
4647d8a to
5b5b4ae
Compare
9af0b9d to
c448c93
Compare
|
hello, @dashed Would you mind following up on this PR to get it landed? |
f0cf25e to
2503730
Compare
|
This pull request has been automatically marked as stale due to inactivity. |
2503730 to
b72d997
Compare
b72d997 to
2a73484
Compare
…cher When auth.mode is "trusted-proxy" and proxy auth fails (e.g. internal connections that bypass the reverse proxy), fall back to token/password credentials if configured. This allows CLI, node hosts, ACP, and other internal services to authenticate directly while external users authenticate via the proxy. Also enable the tailscale overlay for trusted-proxy mode by removing the mode exclusion from the allowTailscale default.
Add 9 unit tests covering fallback behavior: proxy success unchanged, token/password fallback on valid credentials, rejection on mismatch, no-fallback when server credentials unconfigured, rate limiting on fallback attempts, and proxy-takes-priority when both are available. Add 3 e2e tests covering internal connection scenarios: token auth with device identity, token auth without device identity (canSkipDevice), and proxy connection priority over token fallback.
2a73484 to
42556d7
Compare
|
Closing this in favor of #54536. The root cause and touched surface are the same:
Credit preserved here: this PR framed the shared-secret fallback bug clearly and drove the canonical bug path for #17761. |
Summary
Fixes #17761.
The gateway's
authorizeGatewayConnectdispatcher treatstrusted-proxyas a single-mode gate: when proxy auth fails (e.g. internal services connecting directly without the reverse proxy), the function early-returns before reaching the shared-secret (token/password) or Tailscale code paths. This breaks all internal consumers — node host, CLI RPC, ACP, TUI, agent tools, etc.This PR adds an inline shared-secret fallback within the trusted-proxy block:
AuthRateLimiterallowTailscaledefault to not excludetrusted-proxymodeRoot Cause
When
auth.mode === "trusted-proxy", theauthorizeGatewayConnectfunction enters the trusted-proxy block and either succeeds or returns a failure reason. It never falls through to the shared-secret (token/password) block below. Internal services that connect directly (without the reverse proxy) always fail because they can't provide the proxy headers.Changes
src/gateway/auth.ts:limiter/ip/rateLimitScopeabove the trusted-proxy block so the fallback can reuse them:if ("user" in result) { return { ok: true, method: "trusted-proxy", user: result.user }; } + + // Trusted-proxy auth failed — try shared-secret fallback for internal + // services (CLI, node host, ACP) that bypass the reverse proxy. + if (!auth.token && !auth.password) { + return { ok: false, reason: result.reason }; + } + + // Rate-limit fallback attempts + if (limiter) { ... } + + // Try token fallback + if (connectAuth?.token && auth.token) { + if (safeEqualSecret(connectAuth.token, auth.token)) { + limiter?.reset(ip, rateLimitScope); + return { ok: true, method: "token" }; + } + ... + } + + // Try password fallback + if (connectAuth?.password && auth.password) { ... } + + // Client didn't provide matching credentials — return original proxy failure return { ok: false, reason: result.reason };allowTailscaledefault to not excludetrusted-proxymode:src/gateway/auth.test.ts: 9 new unit tests for the fallback path (success, rejection, rate limiting, priority)src/gateway/server.auth.e2e.test.ts: 3 new e2e tests for internal connections with token fallback + device identityConnection flow (after fix)
Related Issues
canSkipDevice/skipPairinggate logicopenclaw node runfails silently with "1008: pairing required" when connecting to a remote gateway #4833 — GatewayClient reconnect behaviorTest Plan
oxlint— 0 errorsoxfmt— cleantsgo— cleanCloses #17761
Related: #8529, #7384, #4833
Rebase History
d5917d37c54a(post-v2026.3.23)330631a0eb39(v2026.3.12)resolveRequestClientIptonet.tsand added bootstrap tokens. No conflicts. Commits:55d625971175,ddd1db37ffa0,f0cf25e4a891.eb0758e1722c(v2026.3.7)fbec3dcadecb,f8b31778c1ad,c448c932f6d5.mainafterfix/trusted-proxy-device-pairingwas absorbed upstream viaconnect-policy.tsrefactoring.