Next.js14集成Auth.js v5登录报错:headers在请求范围外调用
Next.js14 + Auth.js v5 调用signIn时出现
headers was called outside a request scope错误的解决方法 问题背景
在Next.js14项目中按文档搭建最简版Auth.js v5,未修改默认配置,调用signIn登录时触发错误:Error: headers was called outside a request scope。客户端登录处理函数、auth.js配置及路由文件均按文档要求配置,但测试时无法正常进入authorize函数查看用户凭证。
核心原因
Auth.js v5默认导出的signIn是服务器端专属函数,它内部会调用Next.js的headers()等服务器端API。直接在客户端组件中调用该函数时,由于客户端环境不存在请求上下文,会触发上述错误。
解决方案
方案1:使用服务器端Action(推荐,符合Next.js App Router最佳实践)
- 创建服务器端Action文件(如
app/actions/auth.js)
"use server"; import { signIn } from "@/auth"; export async function login(prevState, formData) { try { // 调用服务器端signIn方法 await signIn("credentials", { email: formData.get("email"), password: formData.get("password"), redirect: false, // 可选:设置为true则登录成功后自动跳转,false则返回结果 }); return { success: true, message: "登录成功" }; } catch (error) { return { success: false, error: "登录失败:" + error.message }; } }
- 客户端组件中调用该Action
"use client"; import { login } from "@/app/actions/auth"; import { useFormState } from "react-dom"; export default function LoginForm() { // useFormState用于处理表单状态和错误信息 const [formState, formAction] = useFormState(login, { success: false }); return ( <form action={formAction}> <div> <label>邮箱:</label> <input type="email" name="email" required /> </div> <div> <label>密码:</label> <input type="password" name="password" required /> </div> <button type="submit">登录</button> {formState.error && <p style={{ color: "red" }}>{formState.error}</p>} {formState.success && <p style={{ color: "green" }}>{formState.message}</p>} </form> ); }
方案2:手动封装客户端可用的signIn方法
如果需要直接在客户端逻辑中调用登录接口,可以手动封装一个调用Auth.js API的函数:
- 修改
auth.js配置,导出客户端专用的signIn
import NextAuth from "next-auth"; import Credentials from "next-auth/providers/credentials"; // 保留服务器端的signIn为别名 const { handlers, signIn: serverSignIn, signOut, auth } = NextAuth({ providers: [ Credentials({ credentials: { email: {}, password: {} }, authorize: async (credentials) => { console.log("收到用户凭证:", credentials); // 这里可以添加实际的用户校验逻辑 return { email: credentials.email }; }, }), ], }); // 封装客户端可用的signIn,通过POST请求调用Auth.js的API export const signIn = async (provider, options) => { const response = await fetch(`/api/auth/signin/${provider}`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams(options), }); return await response.json(); }; export { handlers, signOut, auth };
- 客户端组件中直接调用封装后的
signIn
"use client"; import { useState } from "react"; import { signIn } from "@/auth"; export default function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const handleLogin = async (e) => { e.preventDefault(); try { const result = await signIn("credentials", { email, password }); console.log("登录结果:", result); } catch (error) { console.error("登录失败:", error); } }; return ( <form onSubmit={handleLogin}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} required /> <button type="submit">登录</button> </form> ); }
验证效果
完成上述配置后,测试登录功能,authorize函数将正常收到用户凭证并打印,同时不会再触发headers相关的错误。
内容的提问来源于stack exchange,提问作者Cap'n Delirious
相关产品推荐
相关产品推荐

