オンラインプログラミング学習と独学で基礎学習30日間を経て管理画面のあるWebアプリの制作に挑戦中のカキロウです。
カキロウ
今日は管理画面には必須のパスワードの変更機能の実装に挑戦します。
Firebaseの仕様を理解する
公式ドキュメントの通りにコードを記述したにもかかわらず、「FirebaseError: Firebase: Error (auth/requires-recent-login).」とエラーが出て数時間悩んでしまったので、まず仕様から。
公式から引用
アカウントの削除、メインのメールアドレスの設定、パスワードの変更といったセキュリティ上重要な操作を行うには、ユーザーが最近ログインしている必要があります。ユーザーが最近ログインしていない場合、このような操作を行うと失敗し、エラーになります。このような場合は、ユーザーから新しいログイン認証情報を取得して reauthenticateWithCredential に渡し、ユーザーを再認証します。
エラーの原因は、ログインしてから時間が経ってしまっているからでした。
メールアドレスやパスワードの変更など重要な処理を行う際は再認証が必要この仕様を理解して実装に入ります。
再認証してからパスワードを更新する流れ
環境
- Firebase 12.9.1
- Vue 3.2.0
フォルダ構造
src ├─ firebase │ ├─ index.js(Firebaseの初期設定ファイル) │ └─ v1 │ ├─ firestore.js │ ├─ storage.js │ └─ auth.js(今回はここに記述しました) │ └─ views ├─ ChangePassword.vue └─ App.vue
auth.js
import { auth } from '@/firebase';
import {
EmailAuthProvider, // 認証情報(credential)を作成する為に必要
reauthenticateWithCredential, // 再認証を行う関数
updatePassword, // パスワードを更新する関数
} from "firebase/auth";
// 再認証
async function reauthenticate(user, loginPassword) {
try {
const credential = EmailAuthProvider.credential(user.email, loginPassword);
await reauthenticateWithCredential(user, credential);
return;
} catch (error) {
console.error('Auth:再認証エラー', error);
throw error;
}
}
// パスワードを更新
export async function updatePasswordWithAuth(currentPassword, newPassword) {
try {
// ログイン中のユーザー情報を取得
const user = auth.currentUser;
if (user) {
// 再認証
await reauthenticate(user, currentPassword)
// パスワード更新
await updatePassword(user, newPassword);
} else {
throw new Error("USER_NOT_LOGGED_IN");
}
} catch (error) {
console.error("パスワードの更新エラーby Auth:", error);
throw error;
}
}
ChangePassword.vue
<template>
<v-sheet width="600" class="mx-auto pa-8">
<h3 class="my-4">パスワードの更新</h3>
<form @submit.prevent="submit" class="mb-4">
<v-text-field
label="現在のパスワード"
variant="outlined"
required
v-model="currentPassword"
></v-text-field>
<v-text-field
label="新しいパスワード"
variant="outlined"
required
v-model="newPassword"
></v-text-field>
<v-btn
type="submit"
color="primary"
>
送信
</v-btn>
<p class="text-red">{{ errorMessage }}</p>
<p class="text-blue">{{ message }}</p>
</form>
</v-sheet>
</template>
<script setup>
import { ref } from 'vue';
const currentPassword = ref('');
const newPassword = ref('');
const message = ref('');
const errorMessage = ref('');
import { updatePasswordWithAuth } from '@/firebase/v1/auth';
const resetForm = () => {
currentPassword.value = '';
newPassword.value = '';
}
const submit = async() => {
try {
await updatePasswordWithAuth(currentPassword.value, newPassword.value);
message.value = 'パスワードの更新に成功しました。';
resetForm();
} catch (error) {
console.error(error);
errorMessage.value = 'パスワードの変更に失敗しました。', error;
}
}
</script>
下記の記事を参考にしたり、ChatGPTやBingChatにアドバイスをもらいながら無事にパスワードを更新できました。
参考
firebase v9のパスワードリセットとメールアドレス変更zenn