iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0

為什麼需要重新驗證?

在 Firebase 裡,若使用者登入時間太久、或嘗試進行敏感操作(Sensitive Operation),
像是:

  • 更改密碼
  • 更改 email
  • 刪除帳號

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;
  }
};

React 實作範例

這是一個安全版「變更密碼」頁面(需要輸入舊密碼)

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>
  );
}

安全強化建議

  1. 重新登入後修改敏感資料
    • 例如 Email、密碼、刪除帳號,最好都要重新驗證。
    • Firebase 的 Reauth 機制能確保安全性。
  2. 修改密碼後登出
    • 讓舊的 session 全部失效,避免他人仍持有 Token。
    • 可在成功修改密碼後呼叫:
import { signOut } from "firebase/auth";
await signOut(auth);
  1. Redux 中重置 Auth 狀態
    • 若你用 Redux 管理登入狀態,修改密碼後應清除 user 狀態:
dispatch(logout());

上一篇
忘記密碼、重設密碼與變更密碼
下一篇
多重身份驗證(MFA)
系列文
不只是登入畫面!一起打造現代化登入系統26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言