feat(auth): redeem magic links in the installed PWA (iOS handoff)#220
feat(auth): redeem magic links in the installed PWA (iOS handoff)#220
Conversation
- Share consumeMagicLinkForUser between GET verify and new POST magic-pwa-handoff - Store one-time handoff codes in RATE_LIMIT_KV; redeem issues refresh cookie + JWT - iOS non-standalone: exchange email token for handoff URL, defer redeem until Safari or PWA - Manifest launch_handler navigate-existing for Chromium installed apps - Centralize verify page strings Co-authored-by: Jakub Doboš <kubo6472@users.noreply.github.com>
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Co-authored-by: Jakub Doboš <kubo6472@users.noreply.github.com>
Summary
iOS does not share cookies or storage between Mobile Safari and a Home Screen web app, so a magic link opened from Mail often logged the user in only in Safari. This change adds a server-backed handoff: on iPhone/iPad outside standalone mode, the raw email token is exchanged for a short-lived code stored in KV; the SPA replaces the URL with
/auth/verify?handoff=…so the user can open the same URL in the installed app (or finish in Safari).POST /api/auth/redeem-pwa-handoffissues the normal refresh cookie + JWT in whichever context runs it.Chromium PWAs can also reuse an existing client for navigations via
launch_handler.client_mode: navigate-existingin the web manifest.API
POST /api/auth/magic-pwa-handoff— body{ token }; same consume rules asGET /api/auth/verify(including 2FA pending). Full-session path stores{ userId }inRATE_LIMIT_KVunderauth:pwa-handoff:${code}(10 min TTL) and returns{ handoffCode, totpRequired }. If KV is missing, falls back to immediate session (same as GET verify).POST /api/auth/redeem-pwa-handoff— body{ code }; one-time redeem → session response +Set-Cookie.Web
pages/auth/verify.vue— iOS non-standalone: POST handoff →navigateTowithhandoffquery; defer redeem in Safari with copy + “Continue in Safari”; auto-redeem in standalone (display-mode: standalone/navigator.standalone).watch(route.fullPath)so query-only navigations still run the flow.useAuth—magicPwaHandoff,redeemPwaHandoff, exportedMagicPwaHandoffResult.utils/strings.ts— copy for the handoff screen.nuxt.config.ts— manifestlaunch_handler.Files
packages/api/src/auth.ts— sharedconsumeMagicLinkForUser,issueFullMagicSessionResponse, new handlers.packages/api/src/index.ts— route wiring.packages/web/composables/useAuth.ts,pages/auth/verify.vue,utils/strings.ts,nuxt.config.ts.Testing
npm run typecheckin@vmp/api(pass)npx nuxi preparein@vmp/web(pass)Manual verification on a real iPhone (Mail → Safari → Home Screen app) is recommended.