fix(web): redirect to sign-in on 401 instead of failing silently#78
Merged
Conversation
Follow-up to fix/loopback-auth-bypass. That fix made 401 a real, reachable response for the picker's own client JS for the first time — before it, a request from a trusted-looking client essentially never got a 401, so nothing in the browser code had to handle it. Two client-side gaps as a result: - The picker's poll loop (GET /api/sessions every 3s) just caught the resulting error and flipped the status dot to "offline" forever, with no indication the real problem is "sign in again" and no way to get there from the page. - The session-attach page's WS reconnect loop had the same problem, but worse: browsers don't expose a rejected WebSocket handshake's HTTP status at all, so there's no way to even detect "this failed because of auth" from the WS event alone. Fix: install a global fetch() wrapper in both the picker's script and the session-attach page's script — any 401 redirects to /login?returnTo=<path> instead of letting the caller's existing catch block just show a generic failure. For the WS case, the reconnect loop's onclose handler now also fires a throwaway authed fetch (GET /api/sessions) alongside scheduling the reconnect; if the session is actually invalid, that fetch 401s and the wrapper redirects the whole page, tearing down the doomed reconnect loop within one cycle instead of retrying forever. Verified live: loaded the picker with a valid v2 session cookie, cleared the cookie mid-session (simulating expiry/revocation while a tab stays open), and confirmed the next poll cycle (~3s) navigated the browser to /login?returnTo=%2F with the correct page title, rather than sitting on "offline". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Au8T9RPCb6wbgiEecQrBfZ
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
Follow-up to
fix/loopback-auth-bypass(#77). That fix made401a real, reachable response for the picker's own client JS for the first time — a request from a trusted-looking client essentially never got one before, so nothing in the browser code had to handle it.GET /api/sessionsevery 3s) just caught the resulting error and flipped the status dot to "offline" forever — no indication to sign in, no way to get there.Fix
fetch()wrapper in both the picker's script and the session-attach page's script: any401redirects to/login?returnTo=<path>instead of the caller's existing catch block just showing a generic failure.onclosehandler now also fires a throwaway authedfetch('/api/sessions')alongside scheduling the reconnect, so an unauthorized attach surfaces the same redirect within one cycle instead of retrying forever.Test plan
npm run typecheck/npm run buildclean/login?returnTo=%2Fwith the correct page title, instead of sitting on "offline"🤖 Generated with Claude Code
https://claude.ai/code/session_01Au8T9RPCb6wbgiEecQrBfZ