Firebase Google sign-in: should you use a popup or a redirect?

Updated 26 Oct 2026 · Pewterkit Guides

Use signInWithPopup unless you have a reason not to: it works with the default <project>.firebaseapp.com auth domain on browsers that partition third-party storage. Use signInWithRedirect when popups are a poor fit (mobile, blocked popups, a strict COOP header) and you can serve the auth helper from your own domain.

What actually differs

Both methods take the same provider and sign the user in to the same Firebase project. Adapted from Firebase's migration snippet, the code difference is small:

import { GoogleAuthProvider, signInWithPopup, signInWithRedirect, getRedirectResult } from "firebase/auth";

const provider = new GoogleAuthProvider();
// auth = getAuth(app), created once in your Firebase setup module

// Popup: the result comes back from the same call
const cred = await signInWithPopup(auth, provider);

// Redirect: the page leaves; the result is read after it comes back
await signInWithRedirect(auth, provider);
// ...on the next page load:
const credAfterReturn = await getRedirectResult(auth); // null if no redirect was pending

The practical differences are where the flow can break.

Decision table

Question signInWithPopup signInWithRedirect
How the result arrives Promise from the same call getRedirectResult on the next page load
Page and app state Stay as they are Full page navigation; save anything you need first
Browsers that partition third-party storage Works with the default authDomain (Firebase lists it as a fix) Needs extra setup unless the app is on Firebase Hosting at <project>.firebaseapp.com
Mobile Firebase: "less smooth for mobile users" Firebase: "preferred on mobile devices"
Popup blockers Can fail with auth/popup-blocked Not affected
Page sends Cross-Origin-Opener-Policy: same-origin Can break (see below) Not affected
Typical failure Popup errors, listed below Returns signed out; getRedirectResult gives null

(Firebase docs checked Oct 2026.)

When to use signInWithPopup

  • Desktop-first web apps where you cannot serve /__/auth from your own domain. Firebase's redirect guide lists "Switch to signInWithPopup()" as Option 2 for apps hosted outside Firebase.
  • Single-page apps with state you do not want to lose (a half-filled form, a cart, an editor), because the page never navigates away.
  • Quick prototypes: no proxy, no authDomain change, no extra redirect URI.

Call it directly from a click handler. The SDK opens the window with window.open, and if the browser returns no window it throws auth/popup-blocked. Popup errors each have a page: auth/popup-blocked, auth/popup-closed-by-user and auth/cancelled-popup-request.

When to use signInWithRedirect

  • Mobile-first web apps, following Firebase's guidance that redirect "is preferred on mobile devices."
  • Pages that must send Cross-Origin-Opener-Policy: same-origin (for example, for cross-origin isolation).
  • Environments where popups are routinely blocked.

But only after doing one of Firebase's setup options: on Firebase Hosting with a custom domain or web.app, set authDomain to the domain that serves the app; elsewhere, reverse-proxy /__/auth to <project>.firebaseapp.com, self-host the helper files, or sign in with Google's own library and signInWithCredential. Without that, Chrome 115+ and other browsers that partition storage can return users signed out. The full fix list: signInWithRedirect not working.

The COOP header and popups

Cross-Origin-Opener-Policy controls whether a window your page opens stays in the same browsing context group. MDN: with same-origin, a cross-origin document opened by your page goes into a new group, and "any references between the new document and its opener are severed." The Firebase SDK source polls the popup's closed property to detect that the user closed it, and reports auth/popup-closed-by-user. So a page sending same-origin may see that error even though the user did nothing.

Try relaxing the header on the page that starts sign-in:

Cross-Origin-Opener-Policy: same-origin-allow-popups

MDN describes same-origin-allow-popups for cases where a page "needs to open and retain a reference to trusted cross-origin documents," naming OAuth as an example. MDN notes the reference is kept when the opened document's own COOP is unsafe-none, so test the popup after the change. Or switch that page to signInWithRedirect with the setup above.

A hybrid that covers most apps

Try the popup; fall back to a redirect only when the popup is blocked. The fallback still needs the redirect setup above to land signed in.

import { signInWithPopup, signInWithRedirect, getRedirectResult, GoogleAuthProvider } from "firebase/auth";
import { auth } from "./firebase"; // your module that exports getAuth(app)

const provider = new GoogleAuthProvider();

export async function signInWithGoogle() {
  try {
    return await signInWithPopup(auth, provider);
  } catch (error) {
    if (error.code === "auth/popup-blocked") {
      return signInWithRedirect(auth, provider); // page navigates away
    }
    throw error; // closed-by-user, network errors, etc.
  }
}

// Keep this in startup code either way; it returns null when no redirect is pending.
getRedirectResult(auth).catch((error) => console.error(error.code));

Whichever you pick, read the signed-in user from onAuthStateChanged. With redirects, Firebase notes "the onAuthStateChanged observer waits until getRedirectResult resolves before triggering," so the same listener code works for both methods.

How to confirm your choice works

  1. Popup: click sign-in in a normal and a private window on desktop Chrome and Firefox; the window opens, closes itself after Google, and onAuthStateChanged fires with a user.
  2. Redirect: DevTools > Network shows the first navigation going to https://<your authDomain>/__/auth/handler, and after return getRedirectResult resolves with operationType: "signIn" once.
  3. Check your response headers for Cross-Origin-Opener-Policy. If it says same-origin on the sign-in page, use same-origin-allow-popups or redirect.

FAQ

Is signInWithRedirect deprecated?

No. It is still in the current firebase/auth reference. What changed is that it now needs one of Firebase's setup options on browsers that block third-party storage, unless the app runs on Firebase Hosting at <project>.firebaseapp.com.

Which is better on mobile, popup or redirect?

Firebase says the redirect method "is preferred on mobile devices" and that popups are "less smooth for mobile users." On mobile, use redirect with your auth domain set up on your own domain; if you cannot do that setup, a popup is the option that works without it.

Why does my Google popup close straight away with auth/popup-closed-by-user?

Check whether your page sends Cross-Origin-Opener-Policy: same-origin. That header can sever the link between your page and the popup, and the SDK may then read the popup as closed. Try same-origin-allow-popups on that page, or use a redirect there.

Do popup and redirect show the same Google sign-in screen?

Yes. Both go through the handler on your authDomain and then to Google; only how the result returns to your app differs.

Sources

  1. Best practices for using signInWithRedirect on browsers that block third-party storage access
  2. Authenticate Using Google with JavaScript
  3. Manage Users in Firebase
  4. firebase/auth module reference (signInWithPopup, signInWithRedirect, getRedirectResult)
  5. Cross-Origin-Opener-Policy (MDN)
  6. Storage Partitioning (Chrome for Developers)
  7. firebase-js-sdk source: platform_browser/strategies/popup.ts
  8. firebase-js-sdk source: platform_browser/util/popup.ts
  9. firebase-js-sdk source: core/util/handler.ts
  10. firebase-js-sdk source: platform_browser/popup_redirect.ts

How this page was made: drafted with AI from the sources listed, reviewed by Pewterkit. Docs checked 26 Oct 2026. Spotted something out of date? Tell us.

Related guides