You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js12 Middleware调用useAuthState出现Invalid hook call错误怎么解决

错误原因

你遇到的报错核心原因是违反了React Hooks的使用规则:

  • React Hooks(比如useAuthState)只能在React函数组件或自定义Hook的函数体内调用
  • Next.js 12的Middleware运行在独立的Edge Runtime环境中,属于服务端/边缘侧的普通异步函数,不属于React组件执行上下文,完全不支持调用任何React Hook

解决方案

不要在Middleware中使用客户端React Hook做鉴权,改用ID Token校验的方案实现服务端身份验证,步骤如下:

1. 客户端登录成功后写入ID Token到Cookie

修改login.js的登录逻辑,用户完成Firebase登录后,将获取到的ID Token存入Cookie,供Middleware读取:

import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";

function Login() {
  const signInWithGoogle = async () => {
    const auth = getAuth();
    const provider = new GoogleAuthProvider();
    try {
      const result = await signInWithPopup(auth, provider);
      const idToken = await result.user.getIdToken();
      // 存Cookie,有效期1小时,和Firebase ID Token默认有效期一致
      document.cookie = `firebase-token=${idToken}; max-age=3600; path=/`;
      window.location.href = "/";
    } catch (err) {
      console.error("登录失败:", err);
    }
  };

  return (
    <div>
      <button onClick={signInWithGoogle}>Sign in with google</button>
    </div>
  );
}

export default Login;

2. 安装轻量JWT校验库

Firebase Admin SDK不兼容Edge Runtime,选用jose库实现ID Token校验:

npm install jose

3. 重写Middleware鉴权逻辑

替换_middleware.js中的Hook调用逻辑,改为直接校验Cookie中的ID Token有效性:

import { NextResponse } from "next/server";
import * as jose from "jose";

// 替换为你自己的Firebase项目ID
const FIREBASE_PROJECT_ID = "your-firebase-project-id";

export async function middleware(req) {
  const token = req.cookies.get("firebase-token")?.value;
  const { pathname } = req.nextUrl;

  // 登录页直接放行,避免循环重定向
  if (pathname === "/login") {
    return NextResponse.next();
  }

  // 无Token直接跳登录页
  if (!token) {
    return NextResponse.redirect("/login");
  }

  try {
    // 校验Firebase ID Token合法性
    const JWKS = jose.createRemoteJWKSet(new URL("https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com"));
    await jose.jwtVerify(token, JWKS, {
      issuer: `https://securetoken.google.com/${FIREBASE_PROJECT_ID}`,
      audience: FIREBASE_PROJECT_ID,
    });
    // 校验通过放行
    return NextResponse.next();
  } catch (err) {
    // 校验失败清除无效Token,跳登录页
    const res = NextResponse.redirect("/login");
    res.cookies.delete("firebase-token");
    return res;
  }
}

可选简化方案

如果不需要边缘侧鉴权,也可以将鉴权逻辑移到客户端根组件_app.js中调用useAuthState,判断用户未登录时跳转登录页,该方案实现更简单,但安全性低于服务端/边缘侧鉴权。

内容的提问来源于stack exchange,提问作者user16949958

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 07:54:08