Skip to content

Cross-Origin-Opener-Policy エラーの解決法(Firebase Google認証)

問題概要

FirebaseのGoogle認証を使用する際、特にポップアップ認証(signInWithPopup)を行うと、次のエラーがコンソールに表示されることがあります:

plaintext
Cross-Origin-Opener-Policy policy would block the window.closed call

エラーのスクリーンショット例

このエラーが発生しても、認証プロセス自体は正常に完了することが多く、ユーザーデータはFirebaseに保存されます。しかし、エラーメッセージが表示されるのはユーザー体験上好ましくないため、解決が推奨されます。

主な解決策一覧

1. localhostを127.0.0.1に変更(開発環境)

開発環境でlocalhostを使用している場合、127.0.0.1に切り替えると解決することがあります:

json
{
  "scripts": {
    "dev": "vite dev --host=127.0.0.1 --port=3000"
  }
}
<warning> **必須チェック** Firebaseコンソール → Authentication → 承認済みドメインに`127.0.0.1`を追加してください。 </warning>

2. 適切なHTTPヘッダーの設定

Next.jsの場合 (next.config.js)

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

Firebase Hostingの場合 (firebase.json)

json
{
  "hosting": {
    "headers": [
      {
        "source": "**",
        "headers": [
          {
            "key": "Cross-Origin-Opener-Policy",
            "value": "same-origin-allow-popups"
          },
          {
            "key": "Cross-Origin-Embedder-Policy",
            "value": "unsafe-none"
          }
        ]
      }
    ]
  }
}
<tip> **`same-origin-allow-popups`が重要な理由** Google公式が認証ページでこの値の使用を推奨しており、より安全なポップアップ操作を許可します。 </tip>

3. リダイレクト認証方式への切り替え

ポップアップ認証の問題が解決しない場合、リダイレクト方式(signInWithRedirect)が有効です:

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) {
          // 認証後の処理(ユーザーデータ取得など)
        }
      })
      .finally(() => setIsLoading(false));
  }, []);

  const handleLogin = () => {
    signInWithRedirect(auth, provider);
  };

  return (
    <button onClick={handleLogin} disabled={isLoading}>
      {isLoading ? '処理中...' : 'Googleでログイン'}
    </button>
  );
};

追加検証事項

上記を試しても解決しない場合、以下の設定を確認してください:

<warning> **Firebase Consoleでの設定項目チェックリスト**
  1. 認証プロバイダー有効化
    Authentication → ログインプロバイダー → Googleが有効化されているか

    認証プロバイダー設定

  2. 承認済みドメイン
    Authentication → 設定 → 承認済みドメインに現在のドメインが追加されているか

    承認済みドメイン設定

  3. Firebase構成の確認
    firebaseConfigオブジェクトが最新の情報と一致しているか

</warning>

根本原因と対策の技術的背景

このエラーは、ブラウザの新しいセキュリティ仕様Cross-Origin-Opener-Policyに起因しています。Firebase認証が別オリジンのポップアップを使用する際、親ウィンドウとの安全な通信のために以下の設定が求められます:

  1. COOP (Cross-Origin-Opener-Policy)
    same-origin-allow-popups:同一オリジンと許可されたポップアップのみ通信許可

  2. COEP (Cross-Origin-Embedder-Policy)
    unsafe-none:安全でないリソースの読み込みを許可(デフォルト値)

<tip> **なぜ「unsafe-none」なのか?** FirebaseのリソースがCross-Originリソースとして扱われるため、より厳格な設定をするとかえって動作しなくなるケースがあります。 </tip>

FAQ

Q. エラーが出ても認証は成功しています。無視しても良いですか?

A. ユーザー操作に影響がなければ無視しても構いませんが、以下の場合は修正推奨:

  • 一部のブラウザで認証失敗が報告されている
  • プロダクション環境でのエラーログ増加が懸念される

Q. ブラウザをFirefoxに変えると解決しました

A. Chromeの厳格実装が原因のケースがありますが、他のブラウザでも将来同様の仕様が入る可能性が高いため、根本解決を推奨します。

Q. SvelteKit/他のフレームワークでの解決法は?

A. 基本アプローチは同じです:

  1. 開発は127.0.0.1を使用
  2. 本番環境では適切なCOOP/COEPヘッダー設定
  3. フレームワークのルーティング設定で認証ページにヘッダー適用

この対策を行えば、Firebase Google認証におけるCross-Origin-Opener-Policyエラーを解決でき、クライアント側コンソールをクリーンに保てます。