Fix tagged native auth callback handoff

Merged
LA
5mo ago
+1134-258

Summary

  • register tagged dev auth callback schemes and have native auth use the matching cmux-dev-<tag> callback
  • print the CLI fallback sign-in URL and expose auth.sign_in_url over the control socket
  • replace the client after-sign-in page with a localized server route and add a nonce-gated native sign-in wrapper
  • tighten native callback state handling, stale attempt handling, timeout behavior, and auth debug redaction

Mechanism

The normal macOS popup path stays on ASWebAuthenticationSession. Tagged dev builds now register cmux-dev-<tag> in Info.plist and pass that same scheme through the native auth URL. The web handoff enters /handler/native-sign-in, mints an httpOnly handoff cookie, and only auto-opens the native callback when the after-sign-in route sees both the expected stateful callback and matching handoff nonce. Direct/manual fallback links remain click-only.

Verification

  • /Users/lawrence/fun/cmuxterm-hq/skills/autoreview/scripts/autoreview --mode local
  • /Users/lawrence/fun/cmuxterm-hq/skills/autoreview/scripts/autoreview --mode branch --base origin/main
  • swift test in Packages/CmuxAuthRuntime
  • bunx tsc --noEmit in web
  • bash -n scripts/reload.sh && git diff --check
  • xcodebuild -project cmux.xcodeproj -scheme cmux-unit -configuration Debug -destination "platform=macOS" -derivedDataPath /tmp/cmux-safauth-cli-test -only-testing:cmuxTests/AuthEnvironmentTests test
  • CMUX_PORT=4577 CMUX_PORT_RANGE=1 CMUX_PORT_END=4577 ./scripts/reload.sh --tag safauth
  • verified built Info.plist includes cmux-dev-safauth and CMUX_AUTH_CALLBACK_SCHEME=cmux-dev-safauth
  • probed /handler/native-sign-in on http://localhost:4577 and confirmed the handoff cookie + Stack redirect

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


[!NOTE]
High Risk
Touches authentication token handoff, callback validation, and web/native redirect security; regressions could block sign-in or accept wrong callbacks.

Overview
Tagged dev native auth now uses per-tag callback schemes (cmux-dev-<tag>): AuthEnvironment derives them from CMUX_TAG, scripts/reload.sh wires Info.plist URL schemes and env, and sign-in URLs embed cmux_auth_state on the native return URL.

Browser sign-in flow is hardened in HostBrowserSignInFlow: per-attempt cmux_auth_state, manualSignInURL for CLI/socket fallback, stricter external callback routing (state match, stale/sign-out rejection), non-auth ASWebAuthenticationSession completions that wait for a real callback, guarded continuation resumes, and abandoned-attempt timeouts without killing in-flight token validation. Diagnostics add structured logging and broader redaction (including cmux_auth_state).

Control surface: new socket method auth.sign_in_url; CLI cmux auth login prints a fallback sign-in URL before opening the popup.

Web handoff: sign-in enters /handler/native-sign-in (httpOnly handoff nonce) instead of Stack sign-in directly; after-sign-in moves to a localized server route.ts that only auto-opens native when scheme, state, and nonce align; manual fallback stays click-only. i18n strings added for the return page.

Tests expand HostBrowserSignInFlow, AuthDebugLog, AuthEnvironment, and execution-policy coverage.

Reviewed by Cursor Bugbot for commit 1f1cb272e82e7db27c1a7a1313b7888171db63e9. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Fixes native auth handoff for tagged dev builds and hardens the browser sign-in flow. Tagged schemes now round-trip reliably, and Safari/ASWebAuthenticationSession callbacks are state-checked and nonce-gated.

  • New Features

    • Tagged dev builds register and use cmux-dev-<tag>; scripts/reload.sh writes the Info.plist URL scheme and sets CMUX_AUTH_CALLBACK_SCHEME/CMUX_TAG.
    • Added /handler/native-sign-in wrapper and a server /handler/after-sign-in route with an httpOnly handoff cookie and cmux_auth_handoff nonce; auto-open only when state and nonce verify.
    • Exposed auth.sign_in_url on the control socket; the CLI prints a fallback sign-in URL before opening the popup.
    • HostBrowserSignInFlow generates a stateful manualSignInURL, embeds cmux_auth_state in native return URLs, and gates external callbacks by state.
    • Improved diagnostics: more detailed ASWebAuthenticationSession/runtime logs, optional CMUX_DEBUG_LOG path(s), and broader redaction (covers encoded cmux_auth_state and token values).
  • Bug Fixes

    • Strict callback routing: accepts only the active cmux_auth_state; rejects stale/mismatched callbacks and late callbacks after sign-out.
    • Handles non-auth completions from ASWebAuthenticationSession, waits for external callbacks, prevents double resumes, and times out abandoned attempts without canceling in-flight validation.
    • Web after-sign-in route only allows native return URLs for trusted schemes (cmux, cmux-nightly, and local cmux-dev[-tag]) to prevent unintended launches.
    • Expanded tests across runtime and app: tagged scheme/env selection, state/nonce handoff, attempt timeout, mismatch rejection, and external fallback.

Summary by CodeRabbit

  • New Features

    • Fallback sign-in URL in CLI when primary flow unavailable
    • Enhanced native app authentication handoff with improved state tracking
    • New post-sign-in interface with localized messaging (20+ languages) and auto-redirect capability
  • Improvements

    • Stronger callback validation and timeout handling to prevent stale requests
    • Improved authentication state management for more reliable flows
  • Tests

    • Expanded authentication and debug logging test coverage