FirebaseAuthenticationで「requires-recent-login」エラーが出るときの対処法

FIrebaseでユーザーメールアドレスの変更などを試みると、こんなエラーが出ることがあります。

quires recent authentication. Log in again before retrying this request.

メールアドレスやパスワードなどの変更をさせる際は、直近でのログイン履歴が必要らしい。

メールアドレスの変更前にクレデンシャル(メールアドレス・パスワード)を照合して再認証することで、メールアドレスの変更ができるようです。

上手くいかなかったコード

const updateEmail = useCallback(
    async (e: FormEvent<HTMLFormElement>) => {
            const user = await firebase.auth().currentUser user .updateEmail(email) .then(() => {}) .catch((error) => { console.log(error) }) }, [email, password] )

カスタムフック内の該当箇所だけ抜粋。
関数updateEmailをコンポーネント内のFormに仕込めばいけるやつです。

userは「 firebase.auth().currentUser 」で持ってくる。

そして公式ドキュメントによれば、メールアドレスのupdateは「user.updateEmail(email)」でできるらしい。
https://firebase.google.com/docs/auth/web/manage-users?hl=ja#set_a_users_email_address

しかしこれを実行すると、このエラーが返ってきました。

quires recent authentication. Log in again before retrying this request.

最近ログインしていないとメールアドレス(たぶんパスワードも)は変更できないらしい。

そりゃそうか・・と思うけどそんなの聞いていない!

でもやり方を調べたらすぐに修正できました。

修正後のコード

const updateEmail = useCallback(
    async (e: FormEvent<HTMLFormElement>) => {
      e.preventDefault()
      const user = await firebase.auth().currentUser
      const credential = await firebase.auth.EmailAuthProvider.credential( //credentialを取得
        currentEmail,
        password
      )
      user.reauthenticateWithCredential(credential).then(() => { //credential情報で再認証
        user
          .updateEmail(email)
          .then(() => {})
          .catch((error) => {
            console.log(error)
          })
      })
    },
    [email, password]
  )

updateEmailを投げる前に2つのことをやっています。

まず「firebase.auth.EmailAuthProvider.credential」に現在のメールアドレスとパスワードを渡して実行。
するとcredentialが返ってくる。このcredentialが一体どんな情報なのかは調べてないので知りませんが、知らなくてもOKでした。

続いてcredential情報を使って「user.reauthenticateWithCredential(credential)」。これで再認証ができるんですね。

.then以下であらためてupdateEmailをすればちゃんとメールアドレス変更できます。

変更後のメールアドレスだけでなく、現在のメールアドレスも別途持っておくところがポイントですね。

今回はこれまで。
ではまた!