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

使用Next-Auth对接Google API时令牌传递问题求助

问题定位与修复方案

1. 补充Google Sheets API权限范围

当前Google OAuth配置仅请求了Drive权限,缺少Sheets API的访问权限,导致令牌无法调用Sheets接口。修改[...nextauth].js中的权限范围:

providers: [
  GoogleProvider({
    clientId: GOOGLE_OAUTH_ID,
    clientSecret: GOOGLE_OAUTH_SECRET,
    checks: 'none',
    authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth?hd=company.com',
    authorization: {
      params: {
        // 根据需求选择只读或读写权限,同时保留Drive权限
        scope: 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/spreadsheets.readonly'
      },
    },
  })
],

注意:修改权限后需让用户重新登录(清除现有Session),否则旧令牌不会包含新权限。

2. 修复Session回调冗余代码

session回调中的token.accessToken是无效代码,直接删除即可,确保令牌正确挂载到session.user:

session: ({ session, token }) => {
  return {
    ...session,
    user: {
      ...session.user,
      role: token.role,
      accessToken: token.accessToken,
      refreshToken: token.refreshToken
    }
  }
},

3. 完善API路由错误处理逻辑

sheets.js中检测到无令牌时未终止后续代码执行,会导致逻辑报错,需添加return终止响应:

if (!accessToken) {
  return res.status(401).json({ error: 'No Access Token' })
}

if (!refreshToken) {
  return res.status(401).json({ error: 'No Refresh Token' })
}

4. 解决令牌刷新后的持久化问题

当前刷新令牌后仅修改session.user.accessToken,不会同步到NextAuth的持久化Session,可通过两种方式修复:

方案一:在JWT回调中自动刷新令牌

修改[...nextauth].js的jwt回调,实现令牌自动刷新:

jwt: async ({ token, account }) => {
  if (account) {
    token.accessToken = account.access_token
    token.refreshToken = account.refresh_token
    token.expiresAt = account.expires_at * 1000 // 转换为毫秒时间戳
  }

  // 令牌未过期则直接返回
  if (Date.now() < token.expiresAt - 60 * 1000) {
    return token
  }

  // 刷新令牌
  const oauth2Client = new google.auth.OAuth2({
    clientId: GOOGLE_OAUTH_ID,
    clientSecret: GOOGLE_OAUTH_SECRET,
  })
  oauth2Client.setCredentials({ refresh_token: token.refreshToken })
  const { credentials } = await oauth2Client.refreshAccessToken()
  
  return {
    ...token,
    accessToken: credentials.access_token,
    expiresAt: Date.now() + credentials.expiry_date * 1000
  }
},

此方案会在每次生成JWT时自动检查并刷新令牌,API路由可直接使用Session中的令牌。

方案二:在API路由中刷新后更新Session

若不想在JWT回调处理,可在sheets.js中刷新令牌后调用updateSession同步:

// 先导入updateSession
import { updateSession } from "next-auth/react"

// 刷新令牌逻辑
if (oauth2Client.isTokenExpiring()) {
  const { tokens } = await oauth2Client.refreshAccessToken()
  const newAccessToken = tokens.access_token

  // 更新Session并持久化
  session.user.accessToken = newAccessToken
  await updateSession({ ...session, user: { ...session.user, accessToken: newAccessToken } }, req, res)
}

组件中的fetch请求需添加credentials: 'include',否则服务器无法获取Session:

const sheet = await fetch(`/api/google/sheets?sheetId=${encodeURIComponent(sheetId)}&sheetName=${encodeURIComponent(sheetName)}&range=${encodeURIComponent(range)}`, {
  credentials: 'include'
})

6. 验证Session导入正确性

确保sheets.js中正确导入getServerSession和authOptions:

import { getServerSession } from "next-auth/next"
import { authOptions } from "../auth/[...nextauth]" // 根据实际文件路径调整
验证步骤
  1. 清除浏览器缓存与现有登录Session
  2. 重新登录应用,确认授权弹窗包含Sheets权限
  3. 调用API路由,检查是否能正常获取Sheets数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 14:35:35