Next.js 13中NextAuth谷歌认证后获取响应对象及令牌方法
NextAuth谷歌登录后无法获取令牌及响应对象的解决方法
你在Next.js 13中使用NextAuth实现谷歌登录时,能完成登录但无法获取响应对象、控制台无输出,且需要拿到谷歌返回的令牌用于服务端验证,问题可以通过以下步骤解决:
一、修正前端会话数据的获取逻辑
你的现有代码存在两个核心问题:useSession的用法错误,且未等待异步的signIn方法完成就尝试读取数据。修改前端代码如下:
import { useSession, signIn } from "next-auth/react"; const LoginButton = () => { // 正确解构useSession返回的会话数据和状态 const { data: session, status } = useSession(); const onClick = async () => { console.log("触发谷歌登录"); // 等待signIn异步操作完成,可指定回调页避免页面跳转清空日志 const loginResult = await signIn("google", { callbackUrl: window.location.href }); // 输出登录直接结果 console.log("登录操作返回结果:", loginResult); // 登录完成后会话已更新,输出完整会话数据 console.log("当前会话信息:", session); }; return <button onClick={onClick}>Sign in</button>; }; export default LoginButton;
关键说明:
useSession返回的是包含data(会话数据)和status(会话状态:loading/authenticated/unauthenticated)的对象,不存在response属性。signIn是异步函数,必须用await等待执行完成,才能拿到实时的登录结果和更新后的会话数据。- 若登录后跳转页面,原页面控制台日志会被清空,可将
callbackUrl设为当前页,或开启浏览器控制台的「Preserve log」选项保留日志。
二、配置NextAuth获取并传递谷歌令牌
默认情况下,NextAuth的会话数据不会包含谷歌返回的令牌,需要通过回调函数将令牌注入会话:
修改你的认证处理代码:
import NextAuth from "next-auth" import GoogleProvider from "next-auth/providers/google"; const handler = NextAuth({ providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID ?? '', clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '' }), ], callbacks: { // 在JWT回调中保存谷歌返回的令牌 async jwt({ token, account }) { if (account) { token.accessToken = account.access_token; token.refreshToken = account.refresh_token; token.expiresAt = account.expires_at; } return token; }, // 将令牌注入会话,让客户端/服务端可读取 async session({ session, token }) { session.user.accessToken = token.accessToken; session.user.refreshToken = token.refreshToken; session.user.expiresAt = token.expiresAt; return session; } } }) export { handler as GET, handler as POST };
获取令牌的两种场景:
- 客户端获取:当会话状态为
authenticated时,直接从会话中读取令牌:
const { data: session, status } = useSession(); if (status === "authenticated") { console.log("谷歌Access Token:", session.user.accessToken); // 可将此令牌发送到你的服务端进行验证 }
- 服务端获取:在服务端路由中通过
getServerSession直接读取会话中的令牌,无需客户端传递:
// app/api/verify-token/route.js import { getServerSession } from "next-auth/next"; import { handler as authOptions } from "../auth/[...nextauth]/route"; export async function GET(request) { const session = await getServerSession(authOptions); if (session) { const googleToken = session.user.accessToken; // 在此调用谷歌验证接口,或传递给你的后端服务完成身份校验 console.log("服务端拿到的谷歌令牌:", googleToken); return new Response(JSON.stringify({ valid: true }), { status: 200 }); } else { return new Response(JSON.stringify({ valid: false }), { status: 401 }); } }
内容的提问来源于stack exchange,提问作者Sahil Singh
相关产品推荐
相关产品推荐

