くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

FirebaseAuthのxxxChanges()の違いと注意点

Firebase Authで現在の認証状態を継続的に取得する方法がいくつかあるけど、
それぞれの違いを整理してみたときの備忘録(*´ω`*)

Admin SDKやFirebaseコンソールを使うと反映されないは罠。。

xxxChanges()の違い

3種類あるが、それぞれ呼び出されるタイミングはこんな感じ。

  • authStateChanges()
    • リスナーの登録直後
    • ユーザーがログインしたとき
    • 現在のユーザーがログアウトしたとき
  • idTokenChanges()
    • authStateChanges()のに加え、
    • 現在のユーザーのトークンが変更されたとき
  • userChanges()
    • idTokenChanges()のに加え、
    • FirebaseAuth.instance.currentUserのメソッド呼び出し時
      • reload() / unlink()
      • updateEmail() / updatePassword()
      • updatePhoneNumber() / updateProfile()

authStateChanges()が一番狭く、
userChanges()が一番広い

Admin SDKで更新時の注意点

ドキュメントを見てみると、以下の注意点が書かれている。

idTokenChanges()
Firebase Admin SDK を使用してカスタム クレームを設定すると、このイベントは次の場合にのみ発生します。

userChanges()
Firebase Admin SDK で User プロファイルを更新しても、idTokenChanges()、userChanges()、authStateChanges() は呼び出されません。
Firebase Admin SDK や Firebase コンソールで User を無効にしたり削除しても、idTokenChanges()、userChanges()、authStateChanges() は呼び出されません。

なので、Admin SDKやFirebaseコンソールを利用して変更した場合、
変更後の情報は即座にクライアント側に反映されない。
無効化や削除しても一定期間ログイン状態のままになってしまう。。

更新されるタイミングとしては、以下の通り。

  • ログインや再認証したとき
  • 古いトークンが期限切れになったとき
  • currentUser.reload()で再取得したとき
  • currentUser.getIdTokenResult(true)でIDトークンを強制更新したとき

また、.reload()getIdTokenResult(true)を呼び出した際には、
user-disableduser-not-foundなどの例外が発生する可能性がある。

対処方法の案

なので、サーバ側でAdmin SDKを使っていたり、 Firebase コンソールからの変更を即座に反映したい場合、
クライアントで更新してやる必要がある。

案としては以下の3つ。万能なのはFirestoreの利用。

  • 定期的に.reload()を呼び出す方法
    • クライアント側でx秒間隔で.reload()を呼び出す
    • 全プラットフォームで使えるが、リクエストが多い
  • Firestoreを使う
    • サーバ側で更新してほしいときに特定のドキュメントを更新
    • クライアント側で対象のドキュメントをlisten()しておき、
      変更があったらcurrentUser.reload()を呼び出す
    • 全プラットフォームで使えるが、firestoreが必要
  • Firebase Cloud Messagingを使う
    • サーバ側でデータメッセージを送信
    • クライアント側でデータメッセージを受け取ったら、
      currentUser.reload()を呼び出す
    • Safariなど一部の環境では利用できない

また、FunctionsのAuthenticationトリガーも使えないか検討したけど、
作成/削除しか無いので、更新時などはハンドリングできない。。


以上!! 意外と罠があってびっくり。。(*´ω`*)

参考にしたサイトさま