如何在NextJS服务端实现用户auth认证令牌刷新?
解决方案
Firebase 客户端 SDK 的
currentUser状态仅存储在浏览器端,getServerSideProps运行在 Node.js 服务端环境,没有同步客户端的 auth 会话,因此必然返回 undefined,不要尝试在服务端调用客户端 auth 方法获取用户状态。
实现逻辑
你需要同时在Cookie中存储ID令牌和刷新令牌,两个值都要在用户登录成功时写入Cookie,建议设置httpOnly: true规避XSS风险,过期时间和刷新令牌有效期对齐即可。捕获ID令牌过期报错后,直接调用Firebase Auth服务端REST接口用刷新令牌换新的ID令牌,再更新Cookie值即可正常继续业务逻辑。
完整代码示例
import nookies from 'nookies'; export async function getServerSideProps(ctx) { const cookies = nookies.get(ctx); const { token: oldIdToken, refreshToken } = cookies; let validIdToken = oldIdToken; try { const client = useClient(validIdToken); // 原有业务逻辑 // ... } catch (err) { // 可根据你使用的SDK实际报错信息调整过期判断条件 if (err.message.includes('ID token has expired') && refreshToken) { try { // 调用Firebase Auth接口换新ID令牌 const tokenRes = await fetch( `https://securetoken.googleapis.com/v1/token?key=${process.env.NEXT_PUBLIC_FIREBASE_API_KEY}`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `grant_type=refresh_token&refresh_token=${refreshToken}` } ); const tokenData = await tokenRes.json(); const newIdToken = tokenData.id_token; validIdToken = newIdToken; // 更新Cookie中的ID令牌 nookies.set(ctx, 'token', newIdToken, { maxAge: 3600, // ID令牌默认有效期1小时 path: '/', httpOnly: true, secure: process.env.NODE_ENV === 'production' }); // 用新令牌重新初始化客户端 const client = useClient(validIdToken); // 重新执行业务逻辑 // ... } catch (refreshErr) { // 刷新令牌也失效时清空Cookie跳转登录 nookies.destroy(ctx, 'token'); nookies.destroy(ctx, 'refreshToken'); return { redirect: { destination: '/login', permanent: false } }; } } else { // 其他非过期异常直接抛出即可 throw err; } } return { props: { // 页面所需入参 } }; }
注意事项
- Firebase Web API Key建议存在环境变量中,不要硬编码在业务代码里
- 生产环境必须开启Cookie的
secure属性,仅允许HTTPS传输令牌 - 刷新令牌失效时直接强制用户重新登录即可,不需要额外重试逻辑
内容的提问来源于stack exchange,提问作者meds
相关产品推荐
相关产品推荐

