Next.js应用仅开发模式正常 Firebase生产环境返回500错误
Next.js部署Firebase生产环境认证失效返回500错误排查方案
问题现象
- 本地开发模式、本地执行
next build后运行均正常,部署到Firebase生产环境后接口返回500错误 - 项目仓库:space-tourism
- 异常触发点为
getServerSideProps中读取Cookie内Firebase认证token的逻辑,开发环境下该逻辑运行正常
相关业务代码
服务端数据获取逻辑
export const getServerSideProps: GetServerSideProps = async (context) => { try { const cookies = nookies.get(context); const { token } = cookies; const planetInfo = await fetchPlanetsInfo("destinations", token); return { props: { data: planetInfo || [], }, }; } catch (e) { context.res.writeHead(302, { Location: "/" }); context.res.end(); return { redirect: { permanent: false, destination: "/", }, props: {} as never, }; } };
前端认证上下文逻辑
export const AuthContextProvider = ({ children }: Props) => { const [user, setUser] = React.useState<any>(null); React.useEffect(() => { return auth.onIdTokenChanged(async (user) => { if (!user) { setUser(null); nookies.set(undefined, "token", "", { path: "/" }); } else { const token = await user.getIdToken(); setUser(user); nookies.set(undefined, "token", token, { path: "/" }); } }); }, []); // 每10分钟强制刷新认证token React.useEffect(() => { const handle = setInterval(async () => { const user = auth.currentUser; console.log(user); if (user) await user.getIdToken(true); }, 10 * 60 * 1000); return () => clearInterval(handle); }, []); return ( <AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider> ); };
排查进展
- 生产环境下
tokenCookie未被正确设置,服务端读取时返回undefined,已通过服务端日志打印验证 - 浏览器抛出Cookie配置相关警告:
The "token" cookie does not have a valid value for the "SameSite" attribute. Soon cookies without the "SameSite" attribute or with an invalid value will be managed as "Lax". This means that the cookie will no longer be sent to third-party contexts. If the application depends on the availability of this cookie in this type of context, add the "SameSite = None" attribute.
警告核心含义:token Cookie未配置有效的SameSite属性,无有效SameSite属性的Cookie将默认按Lax策略处理,不会在第三方请求上下文中携带,第三方场景使用需配置SameSite=None。
修复方案
核心根因:使用nookies.set写入Cookie时未配置生产环境必需的安全属性,现代浏览器会拦截不符合安全规范的Cookie写入,导致服务端无法读取到认证token触发异常,同时现有token定时刷新逻辑存在遗漏,刷新后未同步更新Cookie内容。修复步骤如下:
- 补全Cookie写入的必填安全属性
所有调用nookies.set操作token的位置,补充sameSite、secure配置:同域部署场景设置sameSite: 'lax'即可,存在跨域嵌入/跨域请求场景设置sameSite: 'none';生产环境必须开启secure: true,保证Cookie仅在HTTPS连接下传输。
修改后的Cookie写入示例:
// 登录/token更新时写入Cookie nookies.set(undefined, "token", token, { path: "/", sameSite: "lax", // 跨域场景替换为"none" secure: process.env.NODE_ENV === "production", maxAge: 30 * 24 * 60 * 60, // 按需配置Cookie有效期,单位为秒 }); // 退出登录时清空Cookie nookies.set(undefined, "token", "", { path: "/", sameSite: "lax", secure: process.env.NODE_ENV === "production", maxAge: -1, });
- 修复定时刷新token的逻辑遗漏
现有代码每10分钟调用user.getIdToken(true)刷新token后,没有把新token同步写入Cookie,会导致Cookie内存储的旧token过期失效,补充更新逻辑:
React.useEffect(() => { const handle = setInterval(async () => { const user = auth.currentUser; if (user) { const freshToken = await user.getIdToken(true); // 刷新后同步更新本地Cookie nookies.set(undefined, "token", freshToken, { path: "/", sameSite: "lax", secure: process.env.NODE_ENV === "production", maxAge: 30 * 24 * 60 * 60, }); } }, 10 * 60 * 1000); return () => clearInterval(handle); }, []);
- 部署前校验项
- 确认Firebase托管域名已加入Firebase控制台认证模块的授权域名列表,未授权域名下的认证请求、Cookie写入会被拦截
- 生产环境确保站点已启用HTTPS,
secure: true配置下HTTP站点无法正常写入Cookie - 部署上线后清空浏览器本地存储的旧无效Cookie再测试,避免缓存影响验证结果
内容的提问来源于stack exchange,提问作者Sandrew94
相关产品推荐
相关产品推荐

