認証状態の永続性

Firebase JS SDK を使用すれば、認証状態をどの程度維持するかを指定できます。たとえば、ログインしたユーザーが明示的にログアウトするまで無期限に維持したり、ウィンドウを閉じたときやページをリロードしたときにクリアしたりできます。

ウェブ アプリケーションの場合、デフォルトの動作では、ユーザーがブラウザを閉じた後でもユーザーのセッションが維持されます。これは、同じデバイス上でウェブページを訪れるたびにユーザーが何度もログインする必要がないので便利です。ユーザーにパスワードの再入力を求めたり、SMS 認証の送信を求めたりすると、ユーザー エクスペリエンスが低下する可能性があります。

ただし、以下のようにこの動作が望ましくない場合があります。

  • 機密データが保存されているアプリケーション。このケースでは、ウィンドウやタブを閉じるたびに状態をクリアしたほうがよい場合もあります。このような動作は、ユーザーがログアウトするのを忘れた場合に重要です。
  • 複数のユーザーが共有するデバイスで使用されるアプリケーション。たとえば、図書館のパソコンで実行されているアプリなどです。
  • 複数のユーザーがアクセスできる共有デバイス上のアプリケーション。そのアプリケーションがどのようにアクセスされているかデベロッパー側からはわからないため、セッションを維持するかどうかユーザー側で選択できるようにしたほうがよい場合もあります。このような動作は、ログイン時に [次回から入力を省略] といったオプションを追加することで可能になります。
  • ユーザーが非匿名アカウント(フェデレーション ID、パスワード、電話番号など)にアップグレードするまで、匿名ユーザーのセッションを維持しないほうがよいケース。
  • 異なるタブ上のアプリケーションには別のユーザーとしてログインできるようにしたい場合。デフォルトの動作では、同じ生成元のタブ間では状態が維持されます。

上述のように、デフォルトの永続性をオーバーライドする必要がある場合があります。

サポートされている認証状態の永続性のタイプ

特定の Firebase Auth インスタンスでの認証状態の永続性は、アプリケーションやユーザーの要件に基づいて、次の 3 つのタイプのいずれかを選択できます。

Enum 説明
firebase.auth.Auth.Persistence.LOCAL 「local」 ブラウザ ウィンドウを閉じたり React Native でアクティビティが破棄されたりした場合でも、状態が維持されることを示します。この状態をクリアするには、明示的なログアウトが必要です。Firebase Auth のウェブ セッションは単一のホストを生成元とするため、単一のドメインでのみ永続化されることに注意してください。
firebase.auth.Auth.Persistence.SESSION 「session」 現在のセッションまたはタブでのみ状態が維持され、ユーザーが認証を受けたタブやウィンドウを閉じるとクリアされることを示します。ウェブ アプリケーションのみに適用されます。
firebase.auth.Auth.Persistence.NONE 「none」 状態はメモリにのみ保存され、ウィンドウまたはアクティビティが更新されるとクリアされることを示します。

認証状態の永続性の変更

既存の永続性のタイプは、次のように firebase.auth().setPersistence メソッドを呼び出すことによって指定または変更できます。

Web

import { getAuth, setPersistence, signInWithEmailAndPassword, browserSessionPersistence } from "firebase/auth";

const auth = getAuth();
setPersistence(auth, browserSessionPersistence)
  .then(() => {
    // Existing and future Auth states are now persisted in the current
    // session only. Closing the window would clear any existing state even
    // if a user forgets to sign out.
    // ...
    // New sign-in will be persisted with session persistence.
    return signInWithEmailAndPassword(auth, email, password);
  })
  .catch((error) => {
    // Handle Errors here.
    const errorCode = error.code;
    const errorMessage = error.message;
  });

Web

firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION)
  .then(() => {
    // Existing and future Auth states are now persisted in the current
    // session only. Closing the window would clear any existing state even
    // if a user forgets to sign out.
    // ...
    // New sign-in will be persisted with session persistence.
    return firebase.auth().signInWithEmailAndPassword(email, password);
  })
  .catch((error) => {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
  });

これにより、現在保存されている Auth セッションについて、指定した Auth インスタンスの永続性のタイプが変更され、今後のログイン リクエスト(リダイレクト リクエストを伴うログインを含む)には、このタイプの永続性が適用されます。また、あるタイプのストレージから別のストレージへのコピーが完了すると解決される Promise を返します。永続性を変更した後でログイン メソッドを呼び出すと、その永続性の変更が完了するのを待ったうえで新しい認証状態が適用されます。

ウェブブラウザと React Native アプリのデフォルトは local(ブラウザがこのストレージ メカニズムをサポートしている場合、たとえばサードパーティの Cookie / データが有効な場合など)で、Node.js バックエンドアプリでは none になります。

永続性の動作の概要

現在の永続性の状態を特定する際には、以下の基準が適用されます。

  • 最初に、SDK は認証されたユーザーが存在するかどうかをチェックします。setPersistence が呼び出されない限り、そのユーザーの現在の永続性タイプは、今後のログイン試行時でも適用されます。したがって、ユーザーが以前のウェブページで永続性を session とされたまま新しいページを訪問し、別のユーザーとして再度ログインすると、そのユーザーの状態も session 永続性で保存されます。
  • ユーザーがログインしておらず、永続性が指定されていない場合は、デフォルトの設定が適用されます(ブラウザ アプリケーションでは local)。
  • ユーザーがログインしておらず、新しいタイプの永続性が設定された場合、今後行われるログイン試行時には、そのタイプの永続性が適用されます。
  • ユーザーがログインした状態で永続性タイプが変更された場合、ログインしている既存のユーザーの永続性は新しいものに変更されます。また、今後行われるすべてのログイン試行時に、新しい永続性が適用されます。
  • signInWithRedirect が呼び出されると現在の永続性タイプが維持され、新たにログインしたユーザーに対し OAuth フローの最後に適用されます。永続性が none であった場合も同様です。そのページで永続性が明示的に指定されている場合、リダイレクト フローを開始した前のページから維持されている認証状態の永続性はオーバーライドされます。

    Web

    import { getAuth, setPersistence, signInWithRedirect, inMemoryPersistence, GoogleAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    setPersistence(auth, inMemoryPersistence)
      .then(() => {
        const provider = new GoogleAuthProvider();
        // In memory persistence will be applied to the signed in Google user
        // even though the persistence was set to 'none' and a page redirect
        // occurred.
        return signInWithRedirect(auth, provider);
      })
      .catch((error) => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
      });

    Web

    firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE)
      .then(() => {
        var provider = new firebase.auth.GoogleAuthProvider();
        // In memory persistence will be applied to the signed in Google user
        // even though the persistence was set to 'none' and a page redirect
        // occurred.
        return firebase.auth().signInWithRedirect(provider);
      })
      .catch((error) => {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
      });

ブラウザ内の複数タブの間で予期される動作

タブごとに異なる永続性タイプが使用されている場合、次のような動作が予期されます。状態を保存する永続性タイプは、いかなる場合も複数同時に存在しえません(認証状態を sessionlocal タイプのストレージに同時に保存するなど)。

  • タブごとに、sessionnone の永続性を持つ異なるユーザーとしてログインできます。各タブは、別のタブの状態を認識することはできません。
  • local 永続性を使用してログインしようとすると、すべてのタブで検知され、同時に実行されます。そのユーザーが session または none 永続性を使用して特定のタブでログインしている場合は、その状態がクリアされます。
  • 複数のタブを開いた状態で local 永続性を使用してログインし、あるタブで none または session 永続性に切り替えた場合、そのタブの状態は session または none 永続性に変更され、そのユーザーは他のすべてのタブでログアウトされます。