React集成Firebase Auth后如何用刷新令牌获取过期后的新访问令牌
解决方案
核心原理
- Firebase Auth 已经内置了自动刷新访问令牌的逻辑,不需要你手动计算过期时间、手动调用刷新令牌接口,官方封装的
getIdToken()方法会自动判断令牌有效性,过期自动刷新返回新令牌 - 你当前代码的两个问题:
- 使用的
onAuthStateChanged监听器仅在用户登录/登出/身份状态变更时触发,令牌刷新不会触发该回调,导致你存的accessToken一直是旧的 - 直接读取
user.Aa属于Firebase内部私有属性,打包混淆后属性名会变更,随时会失效,必须使用官方公开API获取令牌
- 使用的
方案1:改造Auth上下文监听逻辑,自动同步最新令牌
把原来的onAuthStateChanged替换为onIdTokenChanged,该监听器会在令牌刷新时自动触发,同步最新令牌到上下文状态:
useEffect(() => { const unsubscribe = auth.onIdTokenChanged(async (user) => { if (user) { const lastSignInTime = new Date(user.metadata.lastSignInTime); const lastSignInTimeTimeStamp = Math.round(lastSignInTime.getTime() / 1000); const yesterdayTimeStamp = Math.round(new Date().getTime() / 1000) - 24 * 3600; if (lastSignInTimeTimeStamp < yesterdayTimeStamp) { logout(); setCurrentUser({ ...currentUser, user: null, isVerified: false, email: '', accessToken: '', }); setLoading(false); return; } // 用官方API获取最新令牌,自动处理过期刷新 const accessToken = await user.getIdToken(); setCurrentUser({ ...currentUser, user: user, isVerified: user.emailVerified, email: user.email, accessToken: accessToken, }); } else { setCurrentUser({ ...currentUser, user: null, isVerified: false, email: '', accessToken: '', }); } setLoading(false); }); return unsubscribe; }, []);
方案2:接口请求前实时获取令牌(更稳妥)
如果你的项目用了axios/fetch封装请求,直接在请求拦截器里每次请求前获取最新令牌,完全不用关心令牌刷新时机,永远不会带过期令牌发请求:
// axios请求拦截器示例 axios.interceptors.request.use(async (config) => { const user = auth.currentUser; if (user) { // 自动判断是否需要刷新,返回最新有效令牌 const token = await user.getIdToken(); config.headers.Authorization = `Bearer ${token}`; } return config; });
注意事项
- 不需要自己存储刷新令牌、自己计算过期时间,Firebase SDK内部已经处理了所有令牌刷新逻辑
- 如果需要主动触发令牌刷新(比如用户权限变更需要更新令牌携带的自定义声明),可以调用
user.getIdToken(true)强制刷新令牌
内容的提问来源于stack exchange,提问作者FlexLuthor
相关产品推荐
相关产品推荐

