為什麼需要重新驗證?
在 Firebase 裡,若使用者登入時間太久、或嘗試進行敏感操作(Sensitive Operation),
像是:
Firebase 都會要求「重新驗證」,
確保是本人操作,而不是被盜用的登入狀態。
reauthenticateWithCredential()
Firebase 提供的重新驗證函式:
import { EmailAuthProvider, reauthenticateWithCredential } from "firebase/auth";
我們會先要求使用者輸入「當前密碼」,
然後用這個密碼重新建立一個 credential
驗證。
import {
getAuth,
updatePassword,
EmailAuthProvider,
reauthenticateWithCredential,
} from "firebase/auth";
export const secureUpdatePassword = async (currentPassword, newPassword) => {
const auth = getAuth();
const user = auth.currentUser;
if (!user) throw new Error("尚未登入");
try {
// 建立憑證(用舊密碼重新驗證身份)
const credential = EmailAuthProvider.credential(user.email, currentPassword);
// 重新驗證
await reauthenticateWithCredential(user, credential);
console.log("使用者重新驗證成功");
// 修改密碼
await updatePassword(user, newPassword);
console.log("密碼已更新成功");
} catch (error) {
console.error("密碼更新失敗:", error.message);
throw error;
}
};
這是一個安全版「變更密碼」頁面(需要輸入舊密碼)
import React, { useState } from "react";
import { secureUpdatePassword } from "../firebase/authService";
export default function ChangePasswordSecure() {
const [currentPassword, setCurrentPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [message, setMessage] = useState("");
const [loading, setLoading] = useState(false);
const handleChange = async (e) => {
e.preventDefault();
setLoading(true);
setMessage("");
try {
await secureUpdatePassword(currentPassword, newPassword);
setMessage("✅ 密碼修改成功,請重新登入。");
} catch (err) {
setMessage(`❌ 錯誤:${err.message}`);
} finally {
setLoading(false);
}
};
return (
<div className="p-4 max-w-md mx-auto">
<h2 className="text-xl font-bold mb-2">安全變更密碼</h2>
<form onSubmit={handleChange} className="space-y-3">
<input
type="password"
value={currentPassword}
onChange={(e) => setCurrentPassword(e.target.value)}
placeholder="目前密碼"
className="w-full p-2 border rounded"
required
/>
<input
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
placeholder="新密碼"
className="w-full p-2 border rounded"
required
/>
<button
type="submit"
disabled={loading}
className="w-full bg-blue-500 text-white py-2 rounded"
>
{loading ? "更新中..." : "更新密碼"}
</button>
</form>
{message && <p className="mt-3 text-sm text-gray-600">{message}</p>}
</div>
);
}
import { signOut } from "firebase/auth";
await signOut(auth);
dispatch(logout());