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

Next.js通过getServerSideProps获取Firebase当前登录用户报错如何解决

问题原因和修复方案

1. 修复auth/unsupported-persistence-type报错

这个报错的根源是firebaseClient.js会在Next.js的服务端渲染阶段也被执行,Node.js服务端环境没有浏览器的会话存储能力,调用setPersistence就会触发不支持的错误。你需要加客户端环境判断,只有在浏览器环境下才设置持久化:

// utils/firebaseClient.js
import firebase from 'firebase';

const firebaseConfig = {
    // 已隐去配置信息
}
if(!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig);
    // 仅在客户端环境设置持久化
    if (typeof window !== 'undefined') {
        firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION);
    }
} else {
    firebase.app();
}

const auth = firebase.auth();
const googleProvider = new firebase.auth.GoogleAuthProvider();

export { firebase, googleProvider, auth };

2. 补充ID Token写入Cookie的逻辑

Firebase默认的身份状态只存在浏览器的IndexedDB/LocalStorage中,服务端无法直接读取,你需要在用户登录成功、Token刷新时主动将ID Token写入Cookie,这样getServerSideProps才能拿到对应凭证:

// pages/index.js
import { auth, googleProvider } from '../utils/firebaseClient';
import nookies from 'nookies';

export default function Authentication() {
  auth.onAuthStateChanged((user) => {
    if(user) window.location.replace('/dashboard');
  });

  // 监听ID Token刷新,自动更新Cookie保证有效性
  auth.onIdTokenChanged(async (user) => {
    if (user) {
      const token = await user.getIdToken();
      nookies.set(null, 'token', token, {
        maxAge: 30 * 24 * 60 * 60,
        path: '/',
        secure: process.env.NODE_ENV === 'production'
      })
    } else {
      nookies.destroy(null, 'token');
    }
  })

  const googleButton = () => {
    auth.signInWithPopup(googleProvider).catch((err) => {
      console.log(err);
    });
  }

  return (
    <>
      <button onClick={googleButton}>使用谷歌账号登录</button>
    </> 
  )
}

3. 完善getServerSideProps逻辑

你当前的代码验证完用户身份后没有把用户信息返回给页面组件,补充对应逻辑即可:

// pages/dashboard.js
import { firebaseAdmin } from '../utils/firebaseAdmin';
import nookies from 'nookies';

export default function Dashboard({ user }) {
  if (!user) {
    return (
      <>
        <h1>加载中</h1>
      </>
    )
  }

  return (
    <>
      <h1>你好 {user.email}</h1>
    </>
  );
}

export async function getServerSideProps(ctx) {
  try {
    const cookies = nookies.get(ctx);
    if (!cookies.token) throw new Error('无登录凭证');
    const user = await firebaseAdmin.auth().verifyIdToken(cookies.token);
    // 将过滤后的用户信息传给页面组件
    return {
      props: {
        user: {
          uid: user.uid,
          email: user.email,
          displayName: user.name
        }
      }
    }
  } catch (err) {
    console.error(err);
    return {
      redirect: {
        destination: '/',
        permanent: false
      }
    }
  }
}

可选优化点

  • 如果担心客户端存储Cookie的安全问题,可以把ID Token发送到自定义API接口,由服务端写入httpOnly、secure属性的Cookie,降低XSS风险
  • 可以封装一个全局的Auth监听高阶组件,统一处理Token刷新和Cookie更新逻辑,避免每个页面重复编写代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:06:04