NextAuth session回调未执行,无法持久化Google OAuth accessToken求助
问题:NextAuth session回调未执行,无法持久化Google accessToken
问题说明
在Next.js项目中使用NextAuth结合Google OAuth实现认证,需要将Google的accessToken持久化到session中以调用Google Calendar API,但发现session()回调完全没有执行,无法完成accessToken的传递。
相关代码
[...nextauth].js
import GoogleProvider from "next-auth/providers/google" import NextAuth from "next-auth/next" export default NextAuth( { providers: [ GoogleProvider({ clientId: PROCESS.ENV.GOOGLE_CLIENT_ID', clientSecret: PROCESS.ENV.GOOGLE_CLIENT_SECRET, authorization: { params: { prompt: "consent", access_type: "offline", response_type: "code", scope: 'openid email profile https://www.googleapis.com/auth/calendar' }, }, callbacks: { async session({ session, token, user }) { session.user.id = token.id; session.accessToken = token.accessToken; // 从未打印 console.log('In here'); return session; }, async jwt({ token, user, account, profile, isNewUser }) { console.log(token); if (user) { token.id = user.id; } if (account) { token.accessToken = account?.access_token; } return token; }, }, }), ], sercet: PROCESS.ENV.JWT_SECRET, session: { strategy: "jwt", }, } )
登录组件
import React, { useState } from 'react'; import {useSession, signIn, signOut} from 'next-auth/react'; import axios from 'axios'; const Login = () => { const x = useSession(); const {data: session} = x const [calendar, setCalendar] = useState({}); const getCalendarData = async () => { console.log(session.accessToken); console.log(x); const options = { method: 'GET', headers: { Authorization: `Bearer ${session.accessToken}`, } }; const url = "https://www.googleapis.com/calendar/v3/calendars/primary"; let data = null try{ data = await axios.get(url, options); setCalendar(data); } catch(error){ console.log(error); } } if(session){ return ( <div> <div> Welcome, {JSON.stringify(session.user)} </div> <div>{JSON.stringify(calendar)}</div> <div><button onClick={() => signOut()}>Sign Out</button></div> <div><button onClick={getCalendarData}>Get Calendar Data</button></div> </div> ); } else{ return( <div> <div> You are not signed in </div> <div><button onClick={() =>signIn()}> Sign in</button></div> </div> ) } }
问题排查与修复
1. 回调配置位置错误
NextAuth的callbacks是顶层配置项,必须和providers、session同级,不能嵌套在GoogleProvider内部。你当前的写法会导致session和jwt回调完全不被NextAuth识别。
2. 拼写错误
配置中的sercet是拼写错误,正确应为secret。这个错误会导致JWT签名/验证失败,直接中断session相关流程。
3. 环境变量大小写错误
Node.js中环境变量的正确写法是process.env,而非大写的PROCESS.ENV,大写写法会导致无法读取到配置值,引发认证流程异常。
修正后的[...nextauth].js
import GoogleProvider from "next-auth/providers/google" import NextAuth from "next-auth/next" export default NextAuth({ providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, authorization: { params: { prompt: "consent", access_type: "offline", response_type: "code", scope: 'openid email profile https://www.googleapis.com/auth/calendar' }, }, }), ], secret: process.env.JWT_SECRET, session: { strategy: "jwt", }, // 回调移至顶层 callbacks: { async session({ session, token }) { session.user.id = token.id; session.accessToken = token.accessToken; console.log('In here'); return session; }, async jwt({ token, user, account }) { if (user) { token.id = user.id; } if (account) { token.accessToken = account.access_token; } return token; }, }, })
登录组件优化建议
- 给
useSession添加required: true配置,确保session加载完成后再渲染内容 - 修复
getCalendarData中data变量的声明错误(原代码用const后重新赋值,会报错)
const { data: session, status } = useSession({ required: true }); // 处理加载状态 if (status === "loading") { return <div>Loading...</div>; }
内容的提问来源于stack exchange,提问作者Darwin74
相关产品推荐
相关产品推荐

