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

使用create-t3-stack时Credentials Provider会话始终返回null求助

问题:NextAuth Credentials登录后Session返回null

我用NextAuth的CredentialsProvider结合数据库验证邮箱密码,登录时signIn返回ok: true,但在getServerSideProps中获取的Session始终为null,已经调试一天了,以下是相关代码:

我的NextAuth配置

CredentialsProvider({
      name: "Credentials",
      credentials: {},
      async authorize(credentials: any) {
        //check user
        const user: any = await prisma.user.findUnique({
          where: {
            email: credentials.email,
          },
        });

        if (!user) {
          throw new Error("No user found");
        }
        console.log("user credentials", user);
        const checkPassword = await compare(
          credentials.password,
          user?.password
        );
        console.log("user?.password", user?.password);

        if (!checkPassword || user.email !== credentials.email) {
          throw new Error("Password or Email dont match");
        }

        return user;
      },
    }),
  ],
  // Include user.id on session
  callbacks: {
    session({ session, user }) {
      if (session.user) {
        session.user.id = user.id;
      }
      return session;
    },
  },
  session: {
    strategy: "jwt",
    },
  },
  jwt: {
    secret: "test",
  },
  secret: "test",
  // pages: {
  //   signIn: "/",
  //   newUser: "/signin",

  //   signOut: "/signout",
  //   error: '/error'
  // },

登录页面的signIn调用

async function onSubmitLoginValues(values: LoginValuesProps): Promise<any> {
    const result = await signIn("credentials", {
      email: values?.email,
      password: values?.password,
      redirect: false,
      callbackUrl: "/",
    });
    console.log("result", result);
    if (result?.ok) router.push("/");
    return result;
  }

signIn返回结果:

error: null
ok: true
status: 200
url: "http://localhost:3000/"

getServerSideProps中获取Session的尝试

export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
const session = await getServerAuthSession(ctx);
if (!session) {
  return {
    redirect: { destination: "/signin", permanent: false },
  };
}
return {
  props: {
    session,
  },
};

//OR
console.log("ctx", ctx);
const response = await fetch("http://localhost:3000/api/auth", {
  method: "GET",
  credentials: "include",
  //@ts-ignore
  headers: {
    Cookie: ctx.req.headers.cookie,
  },
});
console.log("RESPOSNDE", response.json());

if (!response) {
  return {
    redirect: { destination: "/signin", permanent: false },
  };
}
const data = await response.json();
return { props: { data } };
};

解决方案

问题出在JWT会话策略下的回调配置缺失,以下是修复步骤:

1. 补充jwt回调,将用户数据存入JWT

当使用jwt策略时,NextAuth不会自动把authorize返回的用户信息写入JWT,必须通过jwt回调手动处理:

callbacks: {
  // 新增jwt回调
  async jwt({ token, user }) {
    // 用户登录成功时,将authorize返回的user数据合并到token
    if (user) {
      token.id = user.id;
      token.email = user.email;
    }
    return token;
  },
  // 修改session回调,从token取数据而非user参数
  async session({ session, token }) {
    if (session.user) {
      session.user.id = token.id as string;
      session.user.email = token.email as string;
    }
    return session;
  },
},

注意:在jwt策略下,session回调的第二个参数是token而非user,你之前的代码错误地使用了user参数,导致无法赋值用户ID。

2. 优化authorize返回值

不要返回完整的用户对象(包含密码),只返回必要字段:

async authorize(credentials: any) {
  const user = await prisma.user.findUnique({
    where: { email: credentials.email },
  });

  if (!user) throw new Error("No user found");
  
  const passwordMatch = await compare(credentials.password, user.password);
  if (!passwordMatch) throw new Error("Password does not match");

  // 只返回需要存入JWT的安全字段
  return { id: user.id, email: user.email };
},

3. 确保getServerAuthSession正确封装

如果你自己封装了getServerAuthSession,要确保它使用官方的getServerSession方法:

// lib/auth.ts
import { getServerSession } from "next-auth/next";
import { authOptions } from "../pages/api/auth/[...nextauth]";

export const getServerAuthSession = async (ctx: any) => {
  return await getServerSession(ctx.req, ctx.res, authOptions);
};

4. 建议使用环境变量存储密钥

不要硬编码jwt.secret和secret,改用环境变量:

jwt: { secret: process.env.NEXTAUTH_SECRET },
secret: process.env.NEXTAUTH_SECRET,

修复后,重新登录,getServerSideProps就能正确获取到Session了。


内容的提问来源于stack exchange,提问作者RicardoFonseca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:15:41