サードパーティのストレージ アクセスをブロックするブラウザで signInWithRedirect を使用する場合のベスト プラクティス

本ドキュメントでは、サードパーティ Cookie をブロックするブラウザでリダイレクト ログインを使用する場合のベスト プラクティスについて説明します。 本番環境のすべてのブラウザで signInWithRedirect() を意図したとおりに機能させるには、ここに記載されているオプションのいずれかに従う必要があります。

概要

お客様とお客様のユーザーに対してシームレスな signInWithRedirect() フローを提供するために、Firebase Authentication JavaScript SDK では、アプリの Firebase Hosting ドメインに接続するクロスオリジンの iframe を使用しています。ただし、このメカニズムは、サードパーティのストレージ アクセスをブロックするブラウザでは機能しません。

ブラウザのストレージ パーティショニング機能を無効にするようユーザーに求めることは現実的ではないため、ユースケースの具体的な仕様に応じて、代わりに以下のいずれかの設定オプションをアプリに適用する必要があります。

  • Firebase Hosting を使用して firebaseapp.com のサブドメインでアプリをホストする場合、この問題による影響はなく、特別な対応は必要ありません。
  • Firebase Hosting を使用してカスタム ドメインまたは web.app のサブドメインでアプリをホストする場合は、オプション 1 を使用します。
  • Firebase 以外のサービスでアプリをホストしている場合は、オプション 2オプション 3オプション 4、またはオプション 5 を使用します。

オプション 1: カスタム ドメインを authDomain として使用するように Firebase 構成を更新する

カスタム ドメインを使用して Firebase Hosting でアプリをホストしている場合は、カスタム ドメインを authDomain として使用するように Firebase SDK を構成できます。これにより、アプリと認証 iframe が同じドメインを使用するようになり、ログインの問題を回避できます(Firebase Hosting を使用しない場合は、別のオプションを使用する必要があります)。認証に使用しているものと同じプロジェクトにカスタム ドメインを設定してあることを確認します。

カスタム ドメインを認証ドメインとして使用するように Firebase 構成を更新する手順は次のとおりです。

  1. カスタム ドメインを authDomain として使用するように Firebase JS SDK を構成します。

    const firebaseConfig = {
      apiKey: "<api-key>",
      authDomain: "<the-domain-that-serves-your-app>",
      databaseURL: "<database-url>",
      projectId: "<project-id>",
      appId: "<app-id>"
    };
    
  1. OAuth プロバイダの承認済みリダイレクト URI のリストに新しい authDomain を追加します。この方法はプロバイダによって異なりますが、一般的な手順は、お使いのプロバイダの「始める前に」セクション(例: Facebook プロバイダ)で確認できます。承認のために更新された URI は https://<the-domain-that-serves-your-app>/__/auth/handler のようになります。末尾の /__/auth/handler が重要です。

    同様に、SAML プロバイダを使用している場合は、新しい authDomain を SAML Assertion Consumer Service(ACS)の URL に追加します。

  2. continue_uri承認済みドメインのリストに含まれていることを確認します。

  3. 必要に応じて Firebase Hosting で再デプロイし、/__/firebase/init.json でホストされている最新の Firebase 構成ファイルを取得します。

オプション 2: signInWithPopup() に切り替える

signInWithRedirect() ではなく signInWithPopup() を使用します。アプリのコードの残りの部分は同じままですが、UserCredential オブジェクトの取得方法が異なります。

Web version 9

  // Before
  // ==============
  signInWithRedirect(auth, new GoogleAuthProvider());
  // After the page redirects back
  const userCred = await getRedirectResult(auth);

  // After
  // ==============
  const userCred = await signInWithPopup(auth, new GoogleAuthProvider());

Web version 8

  // Before
  // ==============
  firebase.auth().signInWithRedirect(new firebase.auth.GoogleAuthProvider());
  // After the page redirects back
  var userCred = await firebase.auth().getRedirectResult();

  // After
  // ==============
  var userCred = await firebase.auth().signInWithPopup(
      new firebase.auth.GoogleAuthProvider());
```

ポップアップ ログインはユーザーにとって必ずしも理想的なものではありません。ポップアップはデバイスやプラットフォームによってブロックされることがあり、モバイル ユーザーにとってはフローがスムーズではありません。ポップアップの使用がアプリにとって問題となる場合は、他のいずれかのオプションを採用する必要があります。

オプション 3: firebaseapp.com へのプロキシ認証リクエスト

signInWithRedirect フローでは、最初にアプリのドメインから Firebase 構成の authDomain パラメータで指定されたドメイン(デフォルトでは .firebaseapp.com)にリダイレクトします。authDomain は、ID プロバイダにリダイレクトするログイン ヘルパーコードをホストします。これが成功すると、再びリダイレクトしてアプリのドメインに戻ります。

認証フローがアプリのドメインに戻ると、ログイン ヘルパー ドメインのブラウザ ストレージへのアクセスが行われます。(コードを自己ホストするための)このオプションと次のオプションにより、ブラウザによってブロックされるクロスオリジンのストレージ アクセスをなくすことができます。

  1. アプリサーバーにリバース プロキシを設定して、https://<app domain>/__/auth/ への GET/POST リクエストが https://<project>.firebaseapp.com/__/auth/ に転送されるようにします。この転送がブラウザに対して透過的であるようにします。302 リダイレクトを使用してこれを行うことはできません。

    nginx を使用してカスタム ドメインを提供する場合、リバース プロキシ構成は次のようになります。

    # reverse proxy for signin-helpers for popup/redirect sign in.
    location /__/auth {
      proxy_pass https://<project>.firebaseapp.com;
    }
    
  2. オプション 1 の手順に沿って、承認済みの redirect_uri、ACS の URL、authDomain を更新します。アプリを再デプロイすると、クロスオリジンのストレージ アクセスは行われなくなります。

オプション 4: ログイン ヘルパー コードを自社ドメイン内でホストする

クロスオリジンのストレージ アクセスをなくす別の方法として、Firebase ログイン ヘルパーコードを自社でホストするという方法があります。ただし、この方法は Apple ログインと SAML では機能しません。このオプションは、オプション 3 のリバースプロキシ設定を実行できない場合にのみ使用してください。

ヘルパーコードをホストする手順は次のとおりです。

  1. 次のコマンドを実行して、<project>.firebaseapp.com ロケーションからホストするファイルをダウンロードします。

    mkdir signin_helpers/ && cd signin_helpers
    wget https://<project>.firebaseapp.com/__/auth/handler
    wget https://<project>.firebaseapp.com/__/auth/handler.js
    wget https://<project>.firebaseapp.com/__/auth/experiments.js
    wget https://<project>.firebaseapp.com/__/auth/iframe
    wget https://<project>.firebaseapp.com/__/auth/iframe.js
    wget https://<project>.firebaseapp.com/__/firebase/init.json
    
  2. 自社のアプリドメインで上記のファイルをホストします。ウェブサーバーが https://<app domain>/__/auth/<filename>https://<app domain>/__/firebase/init.json に応答できるようにします。

    ファイルをダウンロードしてホストするサーバー実装のサンプルをご確認ください。 ファイルを定期的にダウンロードして同期し、最新のバグの修正や機能が確実に反映されるようにすることをおすすめします。

  3. オプション 1 の手順に沿って、承認済みの redirect_uriauthDomain を更新します。アプリを再デプロイすると、クロスオリジンのストレージ アクセスは行われなくなります。

オプション 5: プロバイダのログインを独自に処理する

Firebase Authentication SDK には、複雑なロジックをラップし、別の SDK を組み込まなくても済むようにするための便利なメソッドとして、signInWithPopup()signInWithRedirect() が用意されています。これらのメソッドをまったく使用しないという選択肢もあります。その場合は、プロバイダに個別にログインし、signInWithCredential() を使用してプロバイダの認証情報を Firebase Authentication の認証情報と交換します。たとえば、Google ログイン SDKサンプルコード)を使用して Google アカウントの認証情報を取得してから、次のコードを実行して、新しい Google 認証情報をインスタンス化できます。

Web version 9

  // `googleUser` from the onsuccess Google Sign In callback.
  //  googUser = gapi.auth2.getAuthInstance().currentUser.get();
  const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
  const result = await signInWithCredential(auth, credential);

Web version 8

  // `googleUser` from the onsuccess Google Sign In callback.
  const credential = firebase.auth.GoogleAuthProvider.credential(
      googleUser.getAuthResponse().id_token);
  const result = await firebase.auth().signInWithCredential(credential);

signInWithCredential() を呼び出した後のアプリの他の部分は、それまでと同じように機能します。

Apple の認証情報を取得する手順については、こちらをご覧ください。