fix(proxy): make wrapper auth actually work with current openclaw Control UI#223
Open
cap10bad wants to merge 5 commits into
Open
fix(proxy): make wrapper auth actually work with current openclaw Control UI#223cap10bad wants to merge 5 commits into
cap10bad wants to merge 5 commits into
Conversation
added 5 commits
April 23, 2026 12:13
…aw extension deps
The browser's Basic <SETUP_PASSWORD> header survived dashboard auth and leaked to the gateway, causing token mismatch rejections. Drop the 'only if unset' guard so dashboard Basic auth and gateway Bearer auth no longer fight.
openclaw v2026.4.24 switched the Control UI to read the gateway token from localStorage['openclaw.control.settings.v1'].token and send it inside the WS handshake message payload — bypassing the HTTP Authorization header the wrapper was injecting. Result: after dashboard auth, the Control UI WS connect is rejected with reason=token_missing and the gateway hints 'paste the token in Control UI settings'. Fix: on the first GET / after dashboard auth, serve a tiny bootstrap page that writes the known GATEWAY_TOKEN into localStorage and sets a one-time cookie, then reloads. Subsequent loads go straight to the Control UI with auth already resolved. Token only leaves the authenticated dashboard trust boundary (gated by requireDashboardAuth), same surface as the user pasting it manually.
API clients / CLIs already holding the gateway token were being forced through the browser Basic prompt because requireDashboardAuth only accepted Basic. Now accept 'Authorization: Bearer <GATEWAY_TOKEN>' as an equivalent credential (timing-safe compare) and advertise both schemes in WWW-Authenticate.
The native browser Basic auth dialog is jarring for a production dashboard. Replace it with a styled HTML login page that exchanges SETUP_PASSWORD for a signed session cookie (HMAC of SETUP_PASSWORD, stateless, invalidates on password change). - GET / (HTML) → login page when no valid session - POST /__login → sets oc_dashboard_session cookie on success - Basic/Bearer still accepted for curl/CLI clients; successful Basic login also sets the cookie for subsequent browser requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four related auth fixes that are needed together for the wrapper to work correctly with the current Control UI (openclaw >= v2026.4.24). Originally opened for the first bullet only; extended after verifying end-to-end on a live deployment surfaced the rest.
1.
Authorization: Beareralways overwrites Basic before proxyingattachGatewayAuthHeaderhad a!req?.headers?.authorizationguard. Once the browser cached Basic creds for the dashboard, every subsequent proxied request leakedBasic <SETUP_PASSWORD>to the gateway and was rejected as a token mismatch. Drop the guard — whenOPENCLAW_GATEWAY_TOKENis set, always rewriteAuthorizationtoBearer <token>before the proxy call. PR #164 addressed the WS path; this covers HTTP.2. Bootstrap the gateway token into Control UI localStorage
openclaw v2026.4.24 changed the Control UI auth protocol: the gateway token is now read from
localStorage["openclaw.control.settings.v1"].tokenand sent inside the WS handshake message payload, not the HTTP Authorization header. The wrapper's proxy-level header injection is invisible to the new auth path — connect fails withreason=token_missingand the gateway prints "paste the token in Control UI settings".On the first
GET /after dashboard auth, serve a tiny bootstrap HTML that writesGATEWAY_TOKENintolocalStorage, sets a 1-yearoc_wrapper_bootstrappedcookie, and reloads. Subsequent loads go straight to the Control UI with auth already resolved client-side. Token never leaves the authenticated dashboard trust boundary.3. Accept
Authorization: Bearer <GATEWAY_TOKEN>on the wrapper itselfrequireDashboardAuthpreviously only accepted Basic, so API/CLI clients already holding the gateway token were forced through the browser Basic prompt. Now accept Bearer (timing-safe compare) and advertise both schemes inWWW-Authenticate. Bearer passes through to the gateway unchanged.4. Replace native Basic popup with a styled HTML login + session cookie
The browser's native Basic auth dialog is jarring for a production dashboard. On
GETwithAccept: text/htmland no session, return an HTML login page.POST /__loginvalidatesSETUP_PASSWORDand sets anHMAC(SETUP_PASSWORD)session cookie (30-day, HttpOnly, Secure, SameSite=Lax) — stateless, invalidates automatically on password change. Basic/Bearer still accepted for curl/CLI clients; successful Basic auth also sets the cookie.Test plan
websocket-upgrade-auth) passescurl -H "Accept: text/html" /returns login page (noWWW-Authenticate: Basicchallenge)curl /(no Accept) returnsWWW-Authenticate: Basic ..., Bearer ...(unchanged for scripts)curl -H "Authorization: Bearer <GATEWAY_TOKEN>" /succeeds