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

Next.js部署至Firebase Hosting后Middleware无法读取Cookie的问题求助

Next.js部署至Firebase Hosting后Middleware无法读取Cookie的问题求助

大家好,我遇到了一个困扰很久的问题:我的Next.js 15.1.3项目在本地开发模式下运行完全正常,但部署到Firebase Hosting后,Middleware里就无法读取到设置好的Cookie了,想请教下有没有朋友遇到过类似情况,或者能帮我排查下问题出在哪里?

问题场景说明

用户登录时,我会通过Firebase Auth获取ID Token和Refresh Token,然后调用服务端Action setToken() 在服务端设置HttpOnly Cookie。本地开发时,Middleware能正常读取这些Cookie并做路由校验;但部署到Firebase生产环境后,GET请求的Middleware里完全读不到Cookie,只有POST请求能正常读取。

相关代码细节

1. 前端登录状态监听与服务端Action调用

我在组件的useEffect里监听Firebase Auth的状态变化,当用户登录时获取Token并调用setToken服务端Action:

useEffect(() => {
  const unsubscribe = auth.onAuthStateChanged(async (user) => {
    setCurrentUser(user ?? null);
    if (user) {
      // get the token and refresh token
      const tokenResult = await user.getIdTokenResult();
      const token = tokenResult.token;
      const refreshToken = user.refreshToken;

      if (token && refreshToken) {
        // Call server action with token and refresh token
        await setToken({token, refreshToken});
      }
      const claims = tokenResult.claims;
      setCustomClaims(claims ?? null);
    } else {
      await removeToken();
    }
  });

  return () => unsubscribe();
}, []);

2. 服务端Action setToken() 实现

这个Action的作用是验证Token合法性后,为管理员用户设置服务端Cookie:

export const setToken = async ({
  token,
  refreshToken,
}: {
  token: string;
  refreshToken: string;
}) => {
  try {
    const verifiedToken = await auth.verifyIdToken(token);
    if (!verifiedToken) {
      return;
    }

    const userRecord = await auth.getUser(verifiedToken.uid);

    if (process.env.ADMIN_EMAIL === userRecord.email) {

      auth.setCustomUserClaims(verifiedToken.uid, {
        role: 'admin',
      });

      // this is where the cookies are set server side
      const cookieStore = await cookies();
      cookieStore.set('firebaseAuthToken', token, {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
      });
      cookieStore.set('firebaseAuthRefreshToken', refreshToken, {
        httpOnly: true,        
        secure: process.env.NODE_ENV === 'production',
      });

    }
  } catch (e) {
    console.log(e);
  }
};

3. Middleware 路由校验代码

这部分是Cookie读取和路由拦截的逻辑,生产环境下GET请求进来时token始终为null:

export async function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;

  if (request.method === 'POST') {
     return NextResponse.next();
  }

  const cookieStore = await cookies();
  const token = cookieStore.get('firebaseAuthToken')?.value;

  if (pathname !== '/login') {
    if (!token) {
      return NextResponse.redirect(new URL('/login', request.url));
    }

    const decodedToken = decodeJwt(token);

    if (!isAutherized(decodedToken.role as string | undefined)) {
      return NextResponse.redirect(new URL('/login', request.url));
    }

    return NextResponse.next();
  } else {
    if (token) {
      const decodedToken = decodeJwt(token);

      if (!isAutherized(decodedToken.role as string | undefined)) {
        return NextResponse.next();
      }

      return NextResponse.redirect(new URL('/messages', request.url));
    }

    return NextResponse.next();
  }
}

额外发现

本地开发环境中,不管是GET还是POST请求,Middleware都能正常读取到Cookie;但部署到Firebase Hosting后,只有POST请求能读到Cookie,GET请求里cookieStore.get('firebaseAuthToken')返回的始终是undefined。

项目依赖配置

部署到Firebase时我必须使用firebase-admin@^12.0.0,下面是完整的package.json内容:

{
  "private": true,
  "scripts": {
    "dev": "next dev --turbopack",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@hookform/resolvers": "^3.9.1",
    "@radix-ui/react-alert-dialog": "^1.1.4",
    "@radix-ui/react-aspect-ratio": "^1.1.1",
    "@radix-ui/react-avatar": "^1.1.2",
    "@radix-ui/react-dialog": "^1.1.4",
    "@radix-ui/react-label": "^2.1.1",
    "@radix-ui/react-navigation-menu": "^1.2.3",
    "@radix-ui/react-radio-group": "^1.2.2",
    "@radix-ui/react-select": "^2.1.4",
    "@radix-ui/react-separator": "^1.1.1",
    "@radix-ui/react-slider": "^1.2.2",
    "@radix-ui/react-slot": "^1.1.1",
    "@radix-ui/react-toast": "^1.2.4",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "firebase": "^11.1.0",
    "firebase-admin": "^12.0.0",
    "jose": "^5.9.6",
    "lucide-react": "^0.469.0",
    "next": "15.1.3",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-hook-form": "^7.54.2",
    "tailwind-merge": "^2.6.0",
    "tailwindcss-animate": "^1.0.7",
    "uuid": "^11.0.3",
    "zod": "^3.24.1"
  },
  "devDependencies": {
    "@eslint/eslintrc": "^3",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "15.1.3",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}

有没有朋友能帮我分析下问题根源?是Cookie的设置参数(比如domain、path、SameSite)有遗漏,还是Firebase Hosting的部署配置有什么特殊要求?感谢大家的帮助!

备注:内容来源于stack exchange,提问作者Aimn Blbol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:20:17