Skip to content

fix(auth): PasskeyLoginButton must surface error when desktop IPC bridge is missing - #1004

Merged
2witstudios merged 2 commits into
masterfrom
pu/passkey-desktop-fallback
Apr 14, 2026
Merged

2witstudios merged 2 commits into
masterfrom
pu/passkey-desktop-fallback

Conversation

@2witstudios

Copy link
Copy Markdown
Owner

Summary

Sister PR to #1003. Fixes a client-side regression that #1003 would otherwise introduce: after #1003 tightens POST /api/auth/passkey/authenticate to reject platform: 'desktop' without desktopExchange: true, any Electron build whose preload lacks window.electron.auth.openExternal will hard-400 on passkey sign-in, because PasskeyLoginButton currently silently falls through to the web ceremony when the IPC bridge is unavailable.

The fix lives entirely on the client. The server guard added in #1003 is correct and stays as-is; the legacy raw-token server branch is NOT restored.

Prior fallthrough site — apps/web/src/components/auth/PasskeyLoginButton.tsx:54 (pre-fix):

if (isDesktopPlatform() && window.electron?.auth?.openExternal) {
  // … delegate to system browser, return …
}
// falls through to in-window startAuthentication + POST with platform: 'desktop'
// → 400 under #1003's new validation

Invariant

The client must never POST platform: 'desktop' to /api/auth/passkey/authenticate unless it is also using desktopExchange: true via the external-browser ceremony path. If the IPC bridge that enables the external-browser path is unavailable, the client must surface a clear error to the user — not silently fall through to a code path that will be rejected by the server.

The fix

handleLogin in PasskeyLoginButton.tsx now gates on isDesktopPlatform() first, before reading csrfToken or calling startAuthentication. Inside the desktop branch:

  • If window.electron?.auth?.openExternal is missing → toast "Your desktop app needs to be updated to sign in with a passkey. Please update the app and try again." and return early. No network call is made.
  • If the IPC bridge is present → the existing external-browser delegation block runs unchanged.

Web path is untouched.

Commits

  • RED 83dadc4a — test(auth): red — PasskeyLoginButton must error when desktop bridge missing
  • GREEN 0c4da27b — fix(auth): PasskeyLoginButton requires openExternal IPC for desktop sign-in

Two failing test cases were added to PasskeyLoginButton.desktop.test.tsx:

  1. Desktop + window.electron absent → asserts toast.error matches /desktop app/i, no fetch to any /api/auth/passkey/authenticate*, and startAuthentication not called.
  2. Desktop + window.electron.auth = {} (bridge exists but openExternal missing) → same assertions.

Both failed against the pre-fix component and pass after.

Relationship to #1003

This PR is intended to ship together with #1003 in the same release. Default is to land them as two separate PRs; the orchestrator can fold this into #1003 if that's cleaner.

Test plan

  • New RED cases fail against pre-fix code
  • All 7 cases in PasskeyLoginButton.desktop.test.tsx green after fix
  • pnpm --filter web exec vitest run src/components/auth — 24/24 passing
  • pnpm --filter web typecheck — clean
  • pnpm --filter web lint — no new warnings (pre-existing CalendarView warnings only)
  • pnpm --filter web build — clean

🤖 Generated with Claude Code

2witstudios and others added 2 commits April 13, 2026 23:38
…issing

Adds two failing cases that assert PasskeyLoginButton surfaces an
"update the desktop app" error and posts nothing to the server when
isDesktopPlatform() is true but window.electron.auth.openExternal is
unavailable. Pre-fix the component silently falls through to the web
ceremony, which PR #1003 will now reject at the server with a 400 —
regressing sign-in for older Electron bridges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ign-in

Gates the entire sign-in path on isDesktopPlatform() first. When the
Electron build lacks window.electron.auth.openExternal — older bridges,
partial preload, broken IPC — the component now surfaces a clear
"update the desktop app" toast and returns early instead of silently
falling through to the web ceremony.

Closes a regression that PR #1003 introduces: once the server rejects
platform=desktop without desktopExchange, the previous silent
fallthrough would hard-400 any user on an older desktop bridge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Apr 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pagespace-master-plan Ready Ready Preview, Comment Apr 14, 2026 4:44am

@coderabbitai

coderabbitai Bot commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@2witstudios has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 57 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 3 minutes and 57 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bf73c203-9820-4182-9c42-eb0c83a20e96

📥 Commits

Reviewing files that changed from the base of the PR and between 832a937 and 0c4da27.

📒 Files selected for processing (2)
  • apps/web/src/components/auth/PasskeyLoginButton.tsx
  • apps/web/src/components/auth/__tests__/PasskeyLoginButton.desktop.test.tsx
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pu/passkey-desktop-fallback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@2witstudios
2witstudios merged commit 59ca7ad into master Apr 14, 2026
5 checks passed
@2witstudios
2witstudios deleted the pu/passkey-desktop-fallback branch April 14, 2026 05:08

This branch was previously deployed

1 inactive deployment
Preview — 0c4da27b Deployed Apr 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant