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

NextJS+NextAuth实现Google认证时存用户信息入库并返回Token

NextAuth Google登录同步用户数据至数据库+自定义会话Token实现方案

核心实现逻辑

要达成需求,只需要在原有配置基础上补充3部分逻辑,不需要改动已正常运行的凭证登录流程:

  • 新增signIn回调:识别Google登录请求,拿到Google返回的用户邮箱、姓名等信息后,发送POST请求到本地数据库服务完成用户数据存储
  • 修正原有JWT回调的参数逻辑:读取数据库接口返回的用户数据,写入会话Token
  • (可选)新增session回调:把Token中存储的业务字段暴露给前端,方便页面直接读取用户信息

关键修改点说明

  • Google登录触发时,会自动拿到用户公开的基础信息,不需要额外申请权限
  • 数据库接口返回的用户ID、业务Token等自定义字段,全部存在JWT中,不会丢失
  • 原有凭证登录的逻辑完全保留,不会影响现有账号密码登录功能

修改后完整配置代码

import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google";
import CredentialsProvider from "next-auth/providers/credentials";

export default NextAuth({
  providers: [
    CredentialsProvider({
      async authorize(credentials){
        // 原有凭证登录校验逻辑保持不变
        const res =await fetch('http://localhost:8080/user/login?deviceToken=eEiLMMkzR1ypiCwp068z97:APA91bEiBpfwCmpZ5-ijVU4FKcl-4d0QkuWrBtXgcZRJF06MUw8GJvcBn_4ci-v1IFOD8wMF0bNqEheFq0LR0Vz5hXIktT-7sMwOfR52ULhy14NgjiUUW_0nNs5gBXAZHwhtifJluS7v', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
         },
        body: JSON.stringify(credentials),
      })
      const x=await res.json();
      const user={email:x.user.email,name:`${x.user.firstName} ${x.user.lastName}`};
      if(res.ok && user){
        console.log("logged In");
        return user;
      }
       console.log("login error");
        return null;
    }}),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      authorization: {
        params: {
          prompt: "consent",
          access_type: "offline",
          response_type: "code"
        }
      }
    }),
  ],
  jwt: {
    encryption:true,
  },
  callbacks:{
    // 新增signIn回调,处理Google登录时的用户数据同步
    async signIn({ user, account, profile }) {
      // 仅处理Google登录场景
      if (account.provider === 'google') {
        try {
          // 发送POST请求把用户信息存入数据库
          const res = await fetch('http://localhost:8080/user/google-login?deviceToken=eEiLMMkzR1ypiCwp068z97:APA91bEiBpfwCmpZ5-ijVU4FKcl-4d0QkuWrBtXgcZRJF06MUw8GJvcBn_4ci-v1IFOD8wMF0bNqEheFq0LR0Vz5hXIktT-7sMwOfR52ULhy14NgjiUUW_0nNs5gBXAZHwhtifJluS7v', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              email: user.email,
              name: user.name,
              firstName: profile.given_name,
              lastName: profile.family_name,
              googleOpenId: profile.sub
            })
          })
          const dbResp = await res.json()
          if (res.ok && dbResp.user) {
            // 将数据库返回的用户信息挂载到user对象,供后续JWT回调读取
            user.dbUserInfo = dbResp.user
            return true
          }
          // 接口返回错误时阻止登录
          return false
        } catch (err) {
          console.error('Google登录同步用户数据失败:', err)
          return false
        }
      }
      // 凭证登录直接放行
      return true
    },
    // 修正原有JWT回调,写入数据库返回的自定义字段
    async jwt({ token, user, account }) {
      if (account && user) {
        token.accessToken = account.accessToken;
        // Google登录场景,把数据库返回的信息写入Token
        if (account.provider === 'google' && user.dbUserInfo) {
          token.userId = user.dbUserInfo.id
          token.email = user.dbUserInfo.email
          token.name = `${user.dbUserInfo.firstName} ${user.dbUserInfo.lastName}`
          // 如果后端返回了业务Token,可一并存入
          token.businessToken = user.dbUserInfo.token
        }
        // 凭证登录场景保持原有逻辑
        if (account.provider === 'credentials') {
          token.email = user.email
          token.name = user.name
        }
      }
      return token;
    },
    // 可选:新增session回调,把Token字段暴露给前端会话对象
    async session({ session, token }) {
      session.user.id = token.userId
      session.user.email = token.email
      session.user.name = token.name
      session.accessToken = token.accessToken
      session.businessToken = token.businessToken
      return session
    }
  }
})

注意事项

  • 代码中Google用户入库的接口地址/user/google-login需要替换成你后端实际的接口路径,请求体字段也可以根据后端要求调整
  • 如果生产环境部署,localhost:8080要替换成后端服务的实际可访问域名
  • 若不需要前端读取业务Token等自定义字段,可以去掉session回调,不影响核心功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:27:17