fix: use redirect sign-in on mobile to fix Safari login (#4067)#4070
Conversation
Safari mobile silently blocks the cross-origin signInWithPopup flow. Detect mobile via useOs and use signInWithRedirect there, completing the flow with getRedirectResult on return. Desktop keeps the popup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The
useEffectthat callsgetGoogleRedirectResultruns unconditionally on all platforms; consider gating it withisMobileto avoid unnecessary redirect-result checks and error logging on desktop browsers. - The mobile/desktop branching for Google sign-in is currently split between the page (
useOs/isMobile) and the auth helper; consolidating the OS detection into the auth layer (or passing a more explicit mode enum) would reduce coupling and make the sign-in API easier to use correctly from other callers.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `useEffect` that calls `getGoogleRedirectResult` runs unconditionally on all platforms; consider gating it with `isMobile` to avoid unnecessary redirect-result checks and error logging on desktop browsers.
- The mobile/desktop branching for Google sign-in is currently split between the page (`useOs`/`isMobile`) and the auth helper; consolidating the OS detection into the auth layer (or passing a more explicit mode enum) would reduce coupling and make the sign-in API easier to use correctly from other callers.
## Individual Comments
### Comment 1
<location path="apps/web/src/app/helpers/firebase/auth.ts" line_range="19-24" />
<code_context>
-export const googleSignIn = async () => signInWithPopup(auth, provider);
+// Safari mobile blocks the cross-origin popup flow silently, so redirect there.
+export const googleSignIn = async (isMobile: boolean) => {
+ if (isMobile) {
+ await signInWithRedirect(auth, provider);
+ return null;
+ }
+ return signInWithPopup(auth, provider);
+};
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The `googleSignIn` return type now allows `null`, which could surprise other call sites.
In the mobile branch you now `return null` after `signInWithRedirect`, while the non-mobile branch returns `UserCredential` from `signInWithPopup`, changing the function’s type to `Promise<UserCredential | null>`. That’s harmless here because the result is ignored, but other callers may still assume a non-null credential and dereference it. Consider either making `googleSignIn` explicitly fire-and-forget (`Promise<void`) or moving the redirect-specific logic into a separate function so existing call sites don’t unexpectedly receive `null`.
Suggested implementation:
```typescript
const auth = getAuth(firebaseApp);
const provider = new GoogleAuthProvider();
// Safari mobile blocks the cross-origin popup flow silently, so redirect there.
export const googleSignIn = async (isMobile: boolean): Promise<void> => {
if (isMobile) {
await signInWithRedirect(auth, provider);
return;
}
await signInWithPopup(auth, provider);
};
```
1. Update all call sites of `googleSignIn` to stop using its return value, since it now returns `Promise<void>` instead of a `UserCredential`.
2. If any caller currently relies on the `UserCredential` (e.g. `const cred = await googleSignIn(...);`), refactor that logic to either:
- Call `signInWithPopup` directly where the credential is needed, or
- Introduce a separate helper (e.g. `googleSignInWithCredential`) that preserves the `Promise<UserCredential>` behavior for non-mobile flows.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Code Review by Qodo
1.
|
📝 WalkthroughWalkthroughFirebase Google authentication now selects redirect sign-in for mobile devices while retaining popup sign-in elsewhere. A redirect-result helper was added. The web extension page detects the operating system, processes redirect authentication results, supports test credential sign-in, passes the mobile flag to Google sign-in, updates preload state after successful authentication, and logs authentication failures. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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 |
Address PR review: googleSignIn now returns Promise<void> (the only caller ignores the credential) instead of an ambiguous UserCredential | null. Clarify that redirect is used for mobile web generally, per Firebase guidance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Check if the Pull Request fulfils these requirements
Greptile Summary
This PR fixes Safari (iOS) login by switching from
signInWithPopuptosignInWithRedirecton mobile, where popups are silently blocked. AuseEffecton mount callsgetRedirectResultto complete the sign-in after the browser redirects back to the page.auth.tsadds anisMobileparam togoogleSignInand exportsgetGoogleRedirectResultwrappinggetRedirectResult.page.tsxuses Mantine'suseOs()to computeisMobile, passes it togoogleSignIn, and adds a mount-time effect to pick up the redirect result and trigger preload on return.Confidence Score: 5/5
Safe to merge — the redirect flow is correctly implemented and the popup path is unchanged.
Both the redirect and popup paths are logically correct. Auth state is recovered via onAuthStateChanged in AuthProvider and via getRedirectResult in the mount effect.
The handleSignIn flow in page.tsx deserves a second look to clarify which codepath sets shouldPreloadData for mobile vs desktop.
Reviews (2): Last reviewed commit: "docs: tighten sign-in comments" | Re-trigger Greptile