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

如何使用Next-auth同时存储多个会话

如何用Next-auth实现多应用令牌存储

你开发类似Zapier的集成工具时,需要连接多个第三方应用并保存它们的访问令牌,但Next-auth默认会覆盖单一会话中的令牌信息。下面是实现多应用令牌存储的具体方案:

核心思路

Next-auth的JWT令牌支持扩展自定义数据,我们可以在JWT中维护一个对象,按第三方应用的Provider ID分别存储每个应用的访问令牌、刷新令牌等信息,避免覆盖问题。

修改Auth配置

调整authOptions中的jwt和session回调,实现多账号令牌的存储与传递:

export const authOptions = {
  secret: process.env.NEXTAUTH_SECRET,
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      authorization: {
        params: {
          scope: 'openid https://www.googleapis.com/auth/gmail.compose https://www.googleapis.com/auth/gmail.modify'
        }
      }
    }),
    {
      clientId: process.env.QUICK_BOOKS_CLIENT_ID,
      clientSecret: process.env.QUICK_BOOKS_CLIENT_SECRET,
      id: 'quickbooks',
      name: 'QuickBooks',
      type: 'oauth',
      wellKnown: 'https://developer.api.intuit.com/.well-known/openid_sandbox_configuration',
      authorization: { params: { scope: 'com.intuit.quickbooks.accounting openid profile email phone address' } },
      idToken: true,
      checks: ['pkce', 'state'],
      profile(profile) {
        return {
          id: profile.sub,
          name: profile.name,
          email: profile.email,
          image: profile.picture
        }
      }
    }
    // 可添加更多Provider
  ],
  callbacks: {
    async session({ session, token }) {
      // 将多账号令牌信息挂载到session,供前端访问
      session.accounts = token.accounts || {};
      // 保留用户基础信息
      session.user.id = token.id;
      return session;
    },
    async jwt({ token, account, profile }) {
      // 初始化accounts对象(首次连接应用时创建)
      token.accounts = token.accounts || {};
      
      // 当有新的授权账号时,按Provider ID存储令牌信息
      if (account) {
        token.accounts[account.provider] = {
          accessToken: account.access_token,
          refreshToken: account.refresh_token,
          expiresAt: account.expires_at ? account.expires_at * 1000 : null, // 转换为毫秒时间戳
          providerUserId: profile.sub,
          provider: account.provider
        };
      }
      
      return token;
    }
  }
}

关键细节说明

  1. 令牌存储逻辑:每次用户授权新应用时,jwt回调会把该应用的令牌信息存入token.accounts对象,键为Provider的ID(如google、quickbooks),不会覆盖已有应用的令牌。
  2. 前端访问:通过session.accounts可以获取所有已连接应用的令牌,比如session.accounts.google.accessToken就能拿到Google的访问令牌。
  3. 令牌过期与刷新:如果需要处理令牌过期,可以在jwt回调中检查expiresAt,自动调用Provider的刷新令牌接口更新,并同步到token.accounts中。
  4. 断开应用功能:可以编写API路由,接收Provider ID,解码JWT后删除token.accounts中对应条目,再重新编码JWT并更新会话。

可选优化:数据库存储

如果需要连接大量应用,或者需要持久化令牌信息(避免JWT过期后丢失),建议将令牌存储到数据库中:

  • 创建ConnectedAccount表,关联用户ID、Provider ID、访问令牌、刷新令牌等字段。
  • 在jwt回调中,从数据库拉取用户所有已连接的账号信息,挂载到token.accounts中;新授权时,同时写入数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 13:05:19