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

如何使用Google Refresh Token刷新Google Access Token(Firebase+Vue2场景)

Access Token刷新实现方案

前置配置校验(必须完成,否则无法获取有效Refresh Token)

首先确认你初始化GoogleAuthProvider时已配置必要参数,这是Google返回有效Refresh Token的前提:

  • 必须设置access_type: 'offline'参数
  • 建议添加prompt: 'consent'参数,避免用户已授权场景下Google不返回Refresh Token
  • 已在Google Cloud控制台为对应的OAuth 2.0客户端开启Calendar API权限,并在OAuth同意屏幕配置了日历相关权限范围(如https://www.googleapis.com/auth/calendar.readonly)

Vue2端初始化Provider示例代码:

import firebase from 'firebase/app'
import 'firebase/auth'

const googleProvider = new firebase.auth.GoogleAuthProvider()
// 添加日历访问权限
googleProvider.addScope('https://www.googleapis.com/auth/calendar.readonly')
// 配置获取Refresh Token必须的参数
googleProvider.setCustomParameters({
  access_type: 'offline',
  prompt: 'consent'
})

用户登录成功后,将获取到的Refresh Token、Access Token、过期时间戳存储到对应位置:前端可临时存到localStorage,后端建议存到Firestore对应用户文档中。


方案1:前端直接刷新(适合内部小范围使用的应用)

当检测到Access Token即将过期(可提前5分钟判断,或调用Calendar API返回401状态码时),直接向Google OAuth端点发起请求刷新Token,代码示例:

/**
 * 刷新Google Access Token
 * @param {string} refreshToken 已存储的Refresh Token
 * @returns {object|null} 新的Token信息,刷新失败返回null
 */
async function refreshAccessToken(refreshToken) {
  const CLIENT_ID = '你的Google Cloud OAuth 2.0客户端ID'
  const CLIENT_SECRET = '你的Google Cloud OAuth 2.0客户端密钥'
  try {
    const response = await fetch('https://oauth2.googleapis.com/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        client_id: CLIENT_ID,
        client_secret: CLIENT_SECRET,
        refresh_token: refreshToken,
        grant_type: 'refresh_token'
      })
    })
    const tokenInfo = await response.json()
    return {
      accessToken: tokenInfo.access_token,
      expiresAt: Date.now() + tokenInfo.expires_in * 1000
    }
  } catch (error) {
    console.error('Token刷新失败', error)
    // 刷新失败引导用户重新登录授权
    return null
  }
}

注意:该方案需要将Client Secret放到前端代码中,存在泄露风险,公开面向用户的应用不建议使用。


方案2:Firebase云函数刷新(推荐,安全性更高)

将刷新逻辑放到Firebase云函数侧执行,避免泄露敏感信息,实现步骤如下:

2.1 编写云函数代码

const functions = require('firebase-functions')
const admin = require('firebase-admin')
const fetch = require('node-fetch')
admin.initializeApp()

exports.refreshGoogleToken = functions.https.onCall(async (data, context) => {
  // 校验用户登录状态
  if (!context.auth) {
    throw new functions.https.HttpsError('unauthenticated', '未登录用户无法操作')
  }
  const userId = context.auth.uid
  // 从Firestore取出对应用户的Refresh Token
  const userDoc = await admin.firestore().collection('users').doc(userId).get()
  const refreshToken = userDoc.data().googleRefreshToken

  // 通过云函数配置读取敏感信息,不要硬编码
  const clientId = functions.config().google.client_id
  const clientSecret = functions.config().google.client_secret

  const res = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_id: clientId,
      client_secret: clientSecret,
      refresh_token: refreshToken,
      grant_type: 'refresh_token'
    })
  })
  const newTokenInfo = await res.json()
  // 将新的Token信息更新到Firestore
  await admin.firestore().collection('users').doc(userId).update({
    googleAccessToken: newTokenInfo.access_token,
    googleTokenExpiresAt: Date.now() + newTokenInfo.expires_in * 1000
  })
  return {
    accessToken: newTokenInfo.access_token,
    expiresAt: Date.now() + newTokenInfo.expires_in * 1000
  }
})

2.2 前端Vue2调用云函数获取有效Token

/**
 * 获取可用的Google Access Token,自动处理过期刷新
 * @returns {string} 可用的Access Token
 */
async function getValidAccessToken() {
  const currentUser = firebase.auth().currentUser
  if (!currentUser) throw new Error('用户未登录')
  // 读取当前存储的Token信息
  const userDoc = await firebase.firestore().collection('users').doc(currentUser.uid).get()
  const { googleAccessToken, googleTokenExpiresAt } = userDoc.data()
  // 提前5分钟判断Token是否即将过期
  if (Date.now() < googleTokenExpiresAt - 5 * 60 * 1000) {
    return googleAccessToken
  }
  // 过期则调用云函数刷新
  const refreshResult = await firebase.functions().httpsCallable('refreshGoogleToken')()
  return refreshResult.data.accessToken
}

注意事项

  • Refresh Token只要用户没有主动取消授权、Google账号没有安全风险,就是长期有效的,无需定期刷新,只有当刷新请求返回invalid_grant错误时,才需要引导用户重新登录授权
  • 所有敏感信息(如Client Secret)不要硬编码到前端代码或者云函数代码中,建议通过Firebase云函数配置、环境变量存储
  • 调用Calendar API时如果返回401状态码,直接触发刷新逻辑即可,无需完全依赖本地存储的过期时间判断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:36:03