【Firebase】ユーザーアカウントの削除方法
Firebaseでのユーザーアカウントの削除方法
はじめに
筆者、初めてのFirebaseを使って認証機能を作成してました。
しかし、Authenticationからユーザーのアカウントを削除する方法が公式でも不完全であったためここに記しておきたいと思います。
同じく「どうやってやるの?!」と彷徨っている人の助けになれば幸いです🦧
前提
- 認証方法:GoogleAuthProviderのポップアップモード
- Cloud Fonctionsは使わない(お金かかるから)
→Cloud Functions使えば再認証自体不要でただdeleteUser実行すればいけるっぽい?
つまづきポイント
deleteUser(user)
を実行するだけではできない
🌵単純に↓これにも書いてあるように、deleteUser(user)
を実行することでユーザー削除自体はできるはずだけど...
import { getAuth, deleteUser } from "firebase/auth";
const auth = getAuth();
const user = auth.currentUser;
deleteUser(user).then(() => {
// User deleted.
}).catch((error) => {
// An error ocurred
// ...
});
実際にこのまま実行してみると400エラーが出るはずです。
ドキュメントをよく見てみると、こんなことが
どうやら最近サインインした(認証を行った)人のみしか削除できなさそう。
🌵再認証する必要があるけど公式のコードが詳細に書いてない
↑のドキュメントのユーザーを再認証するにある通りに書くと
import { getAuth, reauthenticateWithCredential } from "firebase/auth";
const auth = getAuth();
const user = auth.currentUser;
// TODO(you): prompt the user to re-provide their sign-in credentials
const credential = promptForCredentials();
reauthenticateWithCredential(user, credential).then(() => {
// User re-authenticated.
deleteUser(user).then(() => {
// User deleted.
}).catch((error) => {
// An error ocurred
// ...
});
}).catch((error) => {
// An error ocurred
// ...
});
多分こんな感じになる。
けど、credentialを作るところの関数promptForCredentials()
部分が何も書かれていなくて、どうやら自分でcredentialを作る処理を書く必要がありそうです。
ちなみにcredentialはユーザーのアカウント情報がつまっているもののことらしい。
🌵credentialの作り方としてEmailProviderパターンの情報しかない
どうやってcredential作るのってなったときに検索してみると↑のようにEmailProvider(メールとパスワード認証)の情報が多く、GoogleAuthPrivider(Google認証)の情報がほとんどありませんでした。
まあでも↑みたいな感じでやるのね~って思い、EmailProviderをGoogleAuthProviderにして引数の情報を見てからidトークンかアクセストークンを入れればよいとわかって
if (currentUser) {
const credential = GoogleAuthProvider.credential(
await currentUser.getIdToken(true),
null
);
...
こんな感じで第1引数にidトークンを入れて第2引数のアクセストークンはnullにして実行してみましたが、invalid id_token in idp response
というエラーが出てidトークンが無効ですと言われてしまいました。
アクセストークンの方をうまいこと入れてみても変わりませんでした。
正解はこれだった!!
ここで使いたいcredentialは、再認証した状態の最新のユーザー情報なのでもう一回ポップアップを通して再認証した状態からうまいこと取得できればいいのか?と思って、ログイン時の認証はどうやって処理を書いてたのか見直してみました。
export const login = (): Promise<UserCredential> => {
const provider = new GoogleAuthProvider();
return signInWithPopup(auth, provider);
};
よく見たら戻り値がPromise<UserCredential>
であり、credentialじゃん!ってなって、このlogin()
を実行した後のreturnに今までの処理を繋げる形で書いてみました。
export const login = (): Promise<UserCredential> => {
const provider = new GoogleAuthProvider();
return signInWithPopup(auth, provider);
};
const auth = getAuth();
const currentUser = auth.currentUser;
if (currentUser) {
- const credential = GoogleAuthProvider.credential(
- await currentUser.getIdToken(true),
- null
- );
// 最近サインインしていないとエラーになってしまうので、再認証してクレデンシャルを取得
login().then((result) => {
const credential = GoogleAuthProvider.credentialFromResult(result);
reauthenticateWithCredential(currentUser, credential!)
.then(() => {
// User re-authenticated.
deleteUser(currentUser)
.then(() => {
// User deleted.
if (user?.id) {
deleteDoc(doc(db, "users", user.id));
}
router.push("/");
})
.catch((error) => {
// An error ocurred
return {
isSuccess: false,
errorMessage: "アカウントの削除に失敗しました",
};
});
})
.catch((error) => {
// An error ocurred
return {
isSuccess: false,
errorMessage: "何らかのエラーが発生しました",
};
});
});
}
これでエラーも出ず、アカウント削除できるようになりました!!
↓このドキュメントにポップアップを出して認証した状態からcredentialを取得するコードがあったので参考にしました。
終わりに
筆者はこのアカウント削除処理に5時間くらい沼ったので、同じく沼りそうな方が沼りかけで済んだし、何なら秒で解決して空飛んだわ!くらいまで手助けになっていたら嬉しいです🦧
Discussion