iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
Modern Web

不只是登入畫面!一起打造現代化登入系統系列 第 16

屋內安全[ 4 / 6 ]:React 串接驗證流程實作

  • 分享至 

  • xImage
  •  

後端準備好了(不論你用的是 Express + Firebase Admin,還是用 MSW 模擬),接下來的重點就是:

前端要怎麼把 Firebase 拿到的 Token,安全地送去 /auth/verify?

這一節會用最小可用的方式帶你完成三件事情:

  1. 從 Firebase SDK 取得 idToken
  2. 把 Token 丟給 /auth/verify
  3. 用 Hook 包起來,未來在任何頁面都能呼叫

從 Firebase 拿到 idToken

假設你已經完成登入(Google / Email 都可以),你可以透過 getIdToken() 拿到目前使用者的 Token:

import { getAuth } from "firebase/auth";

export const getFirebaseToken = async () => {
  const auth = getAuth();
  const user = auth.currentUser;

  if (!user) throw new Error("尚未登入");

  return await user.getIdToken(); // 預設會自動 Refresh Token
};

發送到 /auth/verify(Express 或 MSW 都適用)

export const verifyTokenRequest = async (idToken) => {
  const res = await fetch("/auth/verify", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ idToken }),
  });

  if (!res.ok) throw new Error("Token 驗證失敗");

  return await res.json(); // 例如 { uid, email }
};

打包成 Hook

方便你在登入後、重新整理頁面、或 Protected Route 裡使用:

import { getAuth } from "firebase/auth";

export const useVerifyToken = () => {
  const verifyToken = async () => {
    const auth = getAuth();
    const idToken = await auth.currentUser?.getIdToken();

    if (!idToken) throw new Error("尚未登入或拿不到 Token");

    const res = await fetch("/auth/verify", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ idToken }),
    });

    if (!res.ok) throw new Error("Token 驗證失敗");

    return await res.json(); // 取得 uid / email / claims 等
  };

  return { verifyToken };
};

在 React 內部實際使用

import { useEffect, useState } from "react";
import { useVerifyToken } from "./hooks/useVerifyToken";

export default function App() {
  const { verifyToken } = useVerifyToken();
  const [userData, setUserData] = useState(null);

  useEffect(() => {
    const checkAuth = async () => {
      try {
        const data = await verifyToken();
        setUserData(data);
      } catch (err) {
        console.log("未登入或 Token 驗證失敗");
      }
    };

    checkAuth();
  }, []);

  return (
    <div>
      {userData ? (
        <p>登入成功!歡迎 {userData.email}</p>
      ) : (
        <p>尚未驗證或未登入</p>
      )}
    </div>
  );
}

上一篇
屋內安全[ 4 / 6 ]:JWT 驗證與最小後端實作
下一篇
屋內安全[ 6 / 7 ]:AuthContext + Protected Route 實作
系列文
不只是登入畫面!一起打造現代化登入系統18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言