如何检查Google API access token是否过期?Node.js客户端自动刷新问题
问题原因说明
oauth2Client.getTokenInfo()本质是调用Google官方的令牌校验接口,过期的令牌调用该接口会直接返回400类错误,你之前遇到的抛错属于正常行为- 库自带的自动刷新机制触发需要两个前提:你已经将用户对应的
refresh_token、上次获取的expiry_date(令牌过期时间戳)赋值给oauth2Client实例;你调用的是库封装的API请求方法,而非单独调用getTokenInfo方法,所以你的场景下不会触发自动刷新 - 将
tokens事件监听写在路由内部会导致每次请求都重复注册监听器,属于逻辑错误,自然不会有预期输出
本地判断令牌是否过期的实现方案
你完全不需要调用远程接口,只需要在用户首次授权拿到令牌时,将access_token、refresh_token、expiry_date三个字段和userId绑定存储在你的数据库中,后续本地计算即可得到是否过期的布尔值,不会产生任何报错。
工具函数实现
/** * 判断令牌是否过期 * @param {number} expiryDate 令牌过期时间戳(登录获取令牌时返回的expiry_date字段,单位是毫秒) * @param {number} bufferMs 缓冲时间,单位毫秒,默认提前60秒判定过期,避免网络延迟导致的临界问题 * @returns {boolean} true=需要刷新,false=令牌有效 */ function isTokenExpired(expiryDate, bufferMs = 60 * 1000) { return Date.now() >= (expiryDate - bufferMs); }
该判断逻辑完全在本地执行,不会触发远程请求,也不会因为令牌过期抛出错误。
修正后的路由代码
// 这里需要你先根据请求的userId从你的数据库中取出对应用户存储的expiryDate、refreshToken、accessToken router.get("/api/tokenrefresh/:userId/:accessToken", async function (req, res) { // 1. 从数据库取该用户的令牌相关数据 const userTokenData = await db.query('select expiry_date, refresh_token, access_token from user_tokens where user_id = ?', [req.params.userId]); if (!userTokenData) { return res.status(400).json({error: '用户令牌不存在'}); } // 2. 本地判断是否过期 const needRefresh = isTokenExpired(userTokenData.expiry_date); if (!needRefresh) { return res.json({ refreshNeeded: false, token: userTokenData.access_token }); } // 3. 主动刷新令牌逻辑(你可以根据自己的需求替换为自定义逻辑) oauth2Client.setCredentials({ refresh_token: userTokenData.refresh_token }); try { const {credentials} = await oauth2Client.refreshAccessToken(); // 新的令牌记得更新到数据库 await db.query('update user_tokens set access_token = ?, expiry_date = ? where user_id = ?', [ credentials.access_token, credentials.expiry_date, req.params.userId ]); return res.json({ refreshNeeded: true, token: credentials.access_token }); } catch (e) { // 刷新失败一般是refresh_token也过期了,需要用户重新授权 return res.status(401).json({error: '需要重新登录授权'}); } });
注意事项
- 不要在路由中重复注册
tokens事件监听器,该监听器全局注册一次即可,如果你是单实例处理多用户的场景,更建议直接调用refreshAccessToken方法主动获取新令牌,不要依赖事件回调 - refresh_token默认长期有效,除非用户手动取消授权、超过6个月未使用、同一用户授权的refresh_token超过25个上限,才会失效
内容的提问来源于stack exchange,提问作者InquisitiveTom
相关产品推荐
相关产品推荐

