fix(web): repair Google redirect sign-in and auth navigation timing

GI
4d ago
+288-7

Google redirect sign-in on iPhone Safari returned to login without a session. The deployed app uses based-hardware.firebaseapp.com as its auth domain while running at app.omi.me; Firebase's redirect helper therefore uses third-party iframe storage. Safari blocks that storage. Production also returns 404 for /__/auth/iframe, so there is no same-origin helper workaround. This matches Firebase's documented failure mode; an interactive sign-in on David's device remains a deployment acceptance check.

The exact reported URL correctly decodes to /items with all three repeated task parameters. Firebase's installed SDK passes the full current URL as redirectUrl, and Moonshine reads the full query string. Neither path needs URL repair. A separate desktop defect was verified by regression tests: LoginClient navigated after the popup promise resolved before the auth subscriber published the session, allowing ProtectedRoute to send an anonymous render back to login.

Changes:

  • Use app.omi.me as the production auth domain for Firebase Hosting configuration; preserve configured domains on local/preview hosts.
  • Bundle a transparent GET/POST proxy for Firebase auth helpers into the generated Bun server. Preserve callbacks, provider redirects and query strings; use a fixed project Hosting upstream and exclude application cookies/authorization headers.
  • Permit only same-origin framing on helper responses, preserving other upstream CSP directives. App pages retain their existing framing prohibition.
  • Let the existing authenticated-state effect own navigation for Google and Apple. Preserve mobile redirects, desktop popups, referral claims, existing error messages and safeNextPath security checks.
  • Add tests for proxy behavior, domain selection, delayed auth publication and the exact three-task link. Document deployment configuration and device checks in web/app/docs/firebase-auth.md.

Validation:

  • Regression tests against original LoginClient: both Google and Apple timing tests fail on premature navigation; pass with the fix.
  • cd web/app && bun run check: typecheck, 6 Bun smoke tests and 666 Vitest tests pass.
  • cd web/app && bun run lint: passes with existing unrelated warnings.
  • cd web/app && bun run build with production public build inputs: passes.
  • Generated .moonshine/server.ts smoke: real upstream iframe/handler/javascript requests work; helper framing is SAMEORIGIN; login remains DENY. The Hosting project's init.json is already 404 upstream and is passed through unchanged.
  • scripts/pr-preflight --pr-body-file /tmp/sca763-pr-body.md and OMI_PR_BODY_FILE=/tmp/sca763-pr-body.md make preflight: both pass all 17 selected checks.

Deployment follow-up (no console changes made): verify Google OAuth permits https://app.omi.me/__/auth/handler, Apple's Service ID permits the same domain/return URL. The read-only Firebase project configuration already authorizes omi.me, and the installed SDK accepts its app.omi.me subdomain. Keep existing Firebase Hosting callbacks for other clients. Deploy this server and client together. Complete Google sign-in on iPhone Safari and desktop Chrome with the reported link, plus Apple/referral/cancellation checks. No authenticated browser session was available for a live provider completion here.

Firebase reference: https://firebase.google.com/docs/auth/web/redirect-best-practices#proxy-requests

Failure-Class: none

Existing registered session classes concern stale/replaced session ownership rather than cross-origin OAuth helper storage or premature React navigation.