Commit Graph
4 Commits
Author SHA1 Message Date
roboomp 5e781a9c7a fix(ai): clarified oauth completion close copy
Updated the OAuth success page so Firefox users are told they can close the tab manually while the existing close button and timeout remain best-effort.

Added callback-server coverage for the served success page copy.

Fixes #4855
2026-07-09 17:25:23 +00:00
Dylan Bohlender 54f0a00dd2 fix(oauth): copy-safe URL chunks and loopback-only launch URLs
Resolves the two Codex P2s raised on #4420 that merged unaddressed:

- wrapUrlRows indented every continuation chunk. A multi-row terminal
  selection includes the newline plus that indent; address bars strip
  newlines but preserve or percent-encode embedded spaces, so the
  reassembled URL was corrupted at every chunk boundary - silently,
  when the damage landed inside a query value. Chunk rows now carry
  zero leading bytes (label rows keep their indent), and the test
  reassembly helper concatenates chunks raw instead of stripping the
  indent that previously masked exactly this defect.

- #launchUrlIfSafe advertised a localhost /launch copy target for
  flows whose redirectUri never returns to the loopback server. Its
  catch-comment assumed custom-scheme URIs are non-parseable, but
  new URL('vscode://gitlab.gitlab-workflow/authentication') parses
  fine and sailed through the pathname check. The guard now requires
  an http(s) loopback redirectUri (localhost / 127.0.0.1 / [::1]);
  custom schemes, non-loopback hosts, and unparseable URIs all
  suppress the launch URL. Regression tests cover the GitLab Duo
  vscode:// shape and a fixed non-loopback HTTPS redirect.

Refs #4418
2026-07-05 16:01:30 -06:00
roboomp b25775ecbc fix(mcp): resolve /launch route collision and thread launchUrl through RPC client
Codex review flagged two P2s the reporter (@DylanBohlender) confirmed:

1. OAuthCallbackFlow#handleCallback checked LAUNCH_PATH BEFORE the
   `pathname !== this.callbackPath` guard, so an OMP config that pinned
   the provider callback at `/launch` (via `oauth.callbackPath` or a
   matching `oauth.redirectUri`) had the launch route eat its
   `/launch?code=...&state=...` redirect and 302 it back to the
   authorization URL instead of resolving the callback. Reorder so
   `callbackPath` resolution wins the collision, and suppress `launchUrl`
   in that case (also when `redirectUri`'s pathname resolves to `/launch`
   even without an explicit `callbackPath` override) so UIs never
   advertise a self-redirecting copy target.

2. RpcClient.login's `open_url` listener called
   `onOpenUrl(req.url, req.instructions)` and dropped `launchUrl`, so SDK
   hosts built on the public helper couldn't surface the truncation-safe
   copy target. Extend the callback signature to
   `(url, instructions?, launchUrl?)` and forward the field — backward
   compatible for existing 1-2 arg consumers.

Regression tests in packages/ai/test/callback-server-launch-route.test.ts:
- callbackPath = /launch: launchUrl is undefined AND a
  `/launch?code=...&state=...` request resolves via the callback template
  (200/HTML), never 302s to the authorize URL.
- redirectUri pathname = /launch (callbackPath default): launchUrl still
  suppressed defensively by the parsed-pathname guard so the base class
  never advertises a colliding launch route even when callers skip the
  MCPOAuthFlow path-derivation.
2026-07-03 08:46:28 +00:00
roboomp 97c1d08cce fix(mcp): surface a short launch URL and log Windows opener failures for OAuth
Two independent defects broke /mcp reauth against S256-only providers on
Windows boxes whose PATH no longer references System32:

1. openPath spawned bare rundll32 and swallowed the
   `Executable not found in $PATH` throw with a bare `catch {}`, so the MCP
   controller's outer try/catch was dead and the transcript unconditionally
   claimed "Opening browser automatically...".
2. TUI#prepareLine silently truncates any composed row wider than the
   viewport. MCPAuthorizationLinkPrompt rendered `Copy URL: <full URL>` as a
   single ~271-column line whose trailing parameter is
   code_challenge_method=S256. On the reporter's 270-col terminal the cut
   landed inside that parameter, dropping the method while keeping
   code_challenge — which RFC 7636 §4.3 treats as plain PKCE, which Linear
   correctly rejects with "The plain PKCE method is not allowed. Use S256
   instead."

OAuthCallbackFlow now hosts a `GET /launch` route on the same loopback
callback server it already runs; the route 302-redirects to the pending
authorization URL and is advertised as `OAuthAuthInfo.launchUrl` — a
~30-char copy target no viewport can meaningfully truncate. The MCP OAuth
fallback, /login, setup wizard, auth-broker CLI, and login-dialog all
prefer the launch URL for the visible copy target, keep the full URL in
the OSC 8 hyperlink for click-through, and the MCP flow additionally
stages the copy target on the clipboard via OSC 52 (same pattern the
setup wizard uses).

openPath now resolves rundll32.exe through %SystemRoot%\System32 (with a
C:\Windows fallback when SystemRoot is unset) and logs both synchronous
spawn throws and non-zero exits via the shared logger, so silent
misconfigurations show up in ~/.omp/logs/omp.*.log. The dead try/catch
around openPath in the MCP controller is removed.

Fixes #4418
2026-07-03 08:19:14 +00:00