Next-Auth v4.22.1+NextJS13服务端登出请求失败求助
问题:Next-Auth v4.22.1 + NextJS 13 服务端登出请求失败
背景
使用Next-Auth v4.22.1和NextJS 13,尝试在服务端实现用户登出功能,已知客户端signOut()方法无法在服务端调用(会触发ReferenceError: window is not defined),因此自行编写了/api/nextauth-signout-requests接口,通过POST请求调用/api/auth/signout,但请求失败。
错误信息
nextauth-signout-requests.js - Fetch Error SyntaxError: Unexpected token E in JSON at position 0 API handler should not return a value, received object. API resolved without sending a response for /api/nextauth-signout-requests, this may result in stalled requests.
当前代码(nextauth-signout-requests.js)
const NextAuthSignOutReq = async (req, res) => { if (req.method === 'POST') { try { // Sign out the user const signOut = await fetch(`${HOMEPAGE_URL}/api/auth/signout?callbackUrl=${HOMEPAGE_URL}/api/auth/session`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: await fetch(`${HOMEPAGE_URL}/api/auth/csrf`).then(rs => rs.text()) }); const data = await signOut.json(); if (signOut.status === 200) { // Success console.log('User Signed Out'); return res.status(200); } else { // Fail console.log(`nextauth-signout-requests.js - POST to /auth/signout failed`); return res.status(500); } } catch(err) { // Fail console.log('nextauth-signout-requests.js - Fetch Error ' + err); return res.status(500); } } else { // Error. Not a POST request. They tried GET or PUT etc. res.setHeader('Allow', ['POST']); return res.status(405).json({ 'error': `Method ${req.method} not allowed`}); } } export default NextAuthSignOutReq;
问题原因与解决方案
1. JSON解析错误:Unexpected token E
你的猜测正确,/api/auth/signout默认返回的是HTML重定向页面,而非JSON数据,因此调用signOut.json()会触发解析错误。Next-Auth的signout端点核心逻辑是清除会话并跳转,不支持返回JSON格式响应。
2. CSRF令牌用法错误
服务端场景下无需通过fetch获取CSRF令牌,Next-Auth提供了服务端方法自动处理CS校验,手动传递的令牌格式也不符合要求(signout的POST请求需要表单格式的csrfToken参数,而非纯文本)。
3. API响应未正确结束
代码中return res.status(200);的写法错误,Next.js API路由必须调用end()或json()方法结束响应,否则会导致API resolved without sending a response错误。
修正后的服务端登出接口代码
import { signOut } from "next-auth/react"; import { getServerSession } from "next-auth/next"; import { authOptions } from "./auth/[...nextauth]"; // 导入你的NextAuth配置文件 const NextAuthSignOutReq = async (req, res) => { if (req.method === "POST") { try { // 验证用户是否已登录 const session = await getServerSession(req, res, authOptions); if (!session) { return res.status(401).json({ error: "用户未登录" }); } // 服务端调用signOut,自动处理会话清除与跳转 await signOut({ req, res, callbackUrl: `${process.env.HOMEPAGE_URL}/` // 登出后跳转的目标地址 }); // 如果不需要跳转,可手动清除会话Cookie(替代上面的signOut调用) // res.setHeader("Set-Cookie", [ // `next-auth.session-token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; httponly`, // `next-auth.csrf-token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT` // ]); // return res.status(200).json({ success: true }); } catch (err) { console.error("登出失败:", err); return res.status(500).json({ error: "登出操作失败" }); } } else { res.setHeader("Allow", ["POST"]); return res.status(405).json({ error: `不支持${req.method}请求方法` }); } }; export default NextAuthSignOutReq;
关键说明
- 服务端登出直接使用Next-Auth提供的
signOut方法,传入req和res参数,它会自动处理CSRF校验、会话Cookie清除和页面跳转。 - 若不需要跳转,可手动清除
next-auth.session-token和next-auth.csrf-token两个Cookie,然后返回JSON响应。 - 所有API响应必须通过
res.status(...).json(...)或res.status(...).end()结束,避免请求挂起。
内容的提问来源于stack exchange,提问作者Scottish Smile
相关产品推荐
相关产品推荐

