在做前端登入系統時,你可能會想:「我不是已經用 Firebase Login 登入了嗎?為什麼還要搞一個後端驗證?」別急,這篇文章用最輕鬆的方式帶你理解,還會附上兩種實作方案:真後端 Express + Firebase Admin,以及MSW 模擬後端,適合想快速開發或測試的你。
Firebase SDK 確實可以直接在前端登入,拿到 idToken,你甚至可以直接呼叫 Firebase 的服務。但如果你的應用有 自訂後端 API,就必須驗證這個 Token。原因有三個:
安裝
npm install express firebase-admin dotenv cors
初始化
先建立 firebase-admin 的設定檔(可用 Service Account JSON):
import admin from "firebase-admin";
import dotenv from "dotenv";
dotenv.config();
admin.initializeApp({
  credential: admin.credential.cert(JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT)),
});
export default admin;
建立 server
import express from "express";
import cors from "cors";
import admin from "./firebaseAdmin.js";
const app = express();
app.use(cors());
app.use(express.json());
// 驗證 Token
app.post("/auth/verify", async (req, res) => {
  const { idToken } = req.body;
  try {
    const decodedToken = await admin.auth().verifyIdToken(idToken);
    res.json({ uid: decodedToken.uid, email: decodedToken.email });
  } catch (error) {
    res.status(401).json({ error: "Token 無效或過期" });
  }
});
// 模擬登出
app.post("/auth/logout", (req, res) => {
  // Firebase 後端不直接處理前端 Token,登出由前端清除 Token
  res.json({ message: "登出成功(前端自行清理 token)" });
});
app.listen(process.env.PORT, () => {
  console.log(`Server running on http://localhost:${process.env.PORT}`);
});
這樣你就有一個最小可用的 Firebase 驗證後端了。
如果你不想啟 Express 後端,也可以用 MSW 模擬 API。
安裝 MSW
npm i -D msw
建立 handler
import { rest } from "msw";
export const handlers = [
  rest.post("/auth/verify", (req, res, ctx) => {
    const { idToken } = req.body;
    if (idToken === "fake-token") {
      return res(
        ctx.status(200),
        ctx.json({ uid: "123", email: "user@example.com" })
      );
    }
    return res(ctx.status(401), ctx.json({ error: "Token 無效或過期" }));
  }),
  rest.post("/auth/logout", (req, res, ctx) => {
    return res(ctx.status(200), ctx.json({ message: "登出成功" }));
  }),
];
接 React 使用流程
import { setupWorker } from "msw";
import { handlers } from "./handlers";
export const worker = setupWorker(...handlers);
// index.js 或 main.tsx
if (process.env.NODE_ENV === "development") {
  const { worker } = await import("./mocks/browser");
  worker.start();
}