Fix the shared Claude auth flow: whole sign-in URL, recoverable rejected code
Build App / compute-version (pull_request) Successful in 6s
Build App / build-macos (pull_request) Successful in 2m30s
Build App / build-windows (pull_request) Successful in 5m23s
Build App / build-linux (pull_request) Successful in 5m50s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
Build App / compute-version (pull_request) Successful in 6s
Build App / build-macos (pull_request) Successful in 2m30s
Build App / build-windows (pull_request) Successful in 5m23s
Build App / build-linux (pull_request) Successful in 5m50s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
Two compounding bugs made `claude setup-token` unusable, both measured against 2.1.226 under a pty rather than reasoned about. **The sign-in URL was truncated.** The CLI emits it as an OSC 8 hyperlink and slices the *visible* text of that hyperlink to the terminal width: a 346 character URL arrives at 80 columns as five separate hyperlink emissions, each carrying the whole URL in its parameter and 80 characters of it on screen. The transcript scraper picked up the first slice — a URL that parses, points at claude.com, and cannot authorise anything. The ANSI stripper now surfaces the OSC 8 target and `claude-token-link` carries it to the UI, which prefers it over the scraped text. It still goes through `sanitizeRelayUrl` with the ANTHROPIC_SIGN_IN_HOSTS allowlist before display and again before `openUrl` — an OSC 8 parameter is never rendered, which makes it the easier place to hide a hostile host, not a trusted one. The wrapped-display fallback is kept for CLI versions that print a bare URL. **A rejected code hung the flow.** On a bad paste the CLI prints `OAuth error: Invalid code…` / `Press Enter to retry.` and blocks on stdin instead of exiting; nothing recognised that, so the exec sat until the 15-minute timeout with the UI still saying "Finishing sign-in". Given the first bug handed the user a truncated URL, an invalid code was the likely first outcome. The streamed output is now scanned for that message, `claude-token-code-rejected` reopens the input with an explanation, and the Enter is sent so the next code has a prompt to land in — bounded by MAX_CODE_ATTEMPTS, after which the flow reports a failure. An undeterminable exec exit status is logged rather than silently read as success. **A wrapped token was rejected *and* leaked.** `stty cols` fails silently, and an 80-column fallback splits the ~103 character token across two lines: the parser saw a too-short fragment and failed, while the redactor masked the first line — which carries the `sk-ant-` marker — and printed the second, the tail of a live credential, to the UI in clear. `scan_credential_body` now reassembles a run across hard wraps and both the parser and the redactor use it, so they cannot disagree about where a credential ends. A join only happens across a break at a plausible terminal margin (>= 40 columns) and only for a run not already long enough to be a whole credential — without that second guard a repainting TUI welds one frame's token onto the next frame's first word. The length floor is applied to the reassembled body, so a fragment is still never accepted. Also: `stty cols` raised 200 -> 400 (the URL alone needs ~350), and `ESC ( B` is handled as the three-byte charset designation it is — it prefixes every repaint frame, and treating it as two bytes emitted a stray `B` that could glue itself onto a token and make the parser refuse it. `submit_claude_token_code`'s single-write behaviour is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KSP2KNPhuWKQ4DL5TZEn3k
This commit is contained in:
@@ -509,6 +509,10 @@ This lives in the sidebar under **Settings → Claude Authentication**.
|
||||
code to copy — this flow finishes on an Anthropic-hosted page, not a local callback.
|
||||
4. Paste the code back into Triple-C. The token is captured and written straight to the keychain.
|
||||
|
||||
The code is long and easy to truncate. If Anthropic refuses it, the dialog says so and lets you
|
||||
paste another one without restarting the sign-in — the CLI is still waiting. After a few refusals
|
||||
the flow gives up and reports it rather than sitting there.
|
||||
|
||||
Only one sign-in can run at a time, and the whole flow times out after 15 minutes. A long-lived
|
||||
token requires a Claude subscription; without one, `setup-token` finishes without printing a token
|
||||
and nothing is stored.
|
||||
|
||||
Reference in New Issue
Block a user