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

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最佳实践)

  1. 创建服务器端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 };
  }
}
  1. 客户端组件中调用该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的函数:

  1. 修改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 };
  1. 客户端组件中直接调用封装后的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:40:33