Skip to content

Firebase Google Auth: Cross-Origin-Opener-Policy Error Fix

Problem Statement

When implementing Firebase Google Authentication in Next.js applications, developers often encounter the error: "Cross-Origin-Opener-Policy policy would block the window.closed call." This error appears during the sign-in popup window flow, even when authentication functions correctly and user data is saved in Firebase. The error is browser-related and stems from modern security restrictions around cross-origin interactions between windows.

Error shown in browser console when sign-in popup appears

Switch from Popup to Redirect Authentication

The most effective solution is to avoid using popup-based authentication entirely. Instead, implement the redirect sign-in flow, which bypasses the cross-origin restrictions that trigger the error:

jsx
import { getRedirectResult, signInWithRedirect } from 'firebase/auth';
import { useEffect, useState } from 'react';
import { auth, provider } from '../../services/auth';

const Login = () => {
  const [isLoading, setIsLoading] = useState(false);
  
  useEffect(() => {
    setIsLoading(true);
    getRedirectResult(auth)
      .then(response => {
        if (!response) return;
        // Handle successful authentication
      })
      .catch(error => {
        console.error('Authentication error:', error);
      })
      .finally(() => setIsLoading(false));
  }, []);

  const handleLogin = () => {
    signInWithRedirect(auth, provider)
      .catch(error => console.error('Sign-in redirect failed:', error));
  };

  return (
    <button onClick={handleLogin} disabled={isLoading}>
      {isLoading ? 'Loading...' : 'Sign In With Google'}
    </button>
  );
};

export default Login;

Key implementation notes:

  • Use signInWithRedirect instead of signInWithPopup
  • Handle the redirect result with getRedirectResult in useEffect
  • Manage loading states to prevent duplicate submissions
  • This approach eliminates popup-related errors without compromising functionality

Verify Firebase Configuration

If authentication isn't working, first verify these critical Firebase settings:

  1. Allowed Domains (Firebase Console > Authentication Settings):

    • Ensure your domain (e.g., localhost, 127.0.0.1, yourproductiondomain.com) is listed
    • Development domains: localhost and 127.0.0.1 must be explicitly added
  2. Google Sign-in Method Must be enabled in:

    • Firebase Console > Authentication > Sign-in methods > Google
  3. Correct Firebase Config in your code:

    js
    const firebaseConfig = {
      apiKey: "YOUR_API_KEY",
      authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
      projectId: "YOUR_PROJECT_ID",
      appId: "YOUR_APP_ID"
    };

Configure Security Headers

For Next.js Development

Add unsafe-none to your Next.js headers configuration:

js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Cross-Origin-Embedder-Policy',
            value: 'unsafe-none',
          },
          {
            key: 'Cross-Origin-Opener-Policy',
            value: 'same-origin-allow-popups',
          },
        ],
      },
    ];
  },
};

For Production (Firebase Hosting)

Update your firebase.json:

json
{
  "hosting": {
    "headers": [
      {
        "source": "**",
        "headers": [
          {
            "key": "Cross-Origin-Embedder-Policy",
            "value": "unsafe-none"
          },
          {
            "key": "Cross-Origin-Opener-Policy",
            "value": "same-origin-allow-popups"
          }
        ]
      }
    ]
  }
}

Localhost Workaround

Switch from localhost to 127.0.0.1 in your development setup:

  1. Update your development script:

    json
    "scripts": {
      "dev": "next dev -H 127.0.0.1"
    }
  2. Visit http://127.0.0.1:3000 instead of http://localhost:3000

Important Notes

  • The error often doesn't break functionality - authentication may succeed despite the warning
  • Error may appear in Chrome but not Firefox - use Chrome for development testing
  • Clear cache after header changes - use incognito mode to ensure updated headers are loaded:
    bash
    chrome --incognito

Why These Solutions Work

Modern browsers enforce strict security rules to prevent cross-origin attacks. The signInWithPopup method creates security conflicts with these policies. The redirect solution avoids these conflicts entirely, while the header configurations explicitly relax security rules in a controlled manner. The 127.0.0.1 workaround resolves inconsistencies in how browsers treat localhost.

Production Consideration

For production deployments, always combine:

  1. Redirect authentication method
  2. Correct security headers in hosting configuration
  3. Verified Firebase allowed domains

Security Notes

While unsafe-none resolves the error:

  • Understand security implications before implementing
  • Never combine with sensitive operations requiring strong isolation
  • Consider CSP policies for robust production security