next-auth使用Credentials凭证登录报错

chat

auth.ts:

import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';
import Credentials from 'next-auth/providers/credentials';

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    GitHub,
    Credentials({
      credentials: {
        email: {},
        password: {},
      },
      authorize: async (credentials) => {
        console.log('鉴权---authorize', credentials);
        return {
          id: '1',
          name: 'crayming',
          email: 'crayming@example.com',
          image: null,
        };
      },
    }),
  ],
});

login.tsx:

import { signIn } from '@/auth';

export default function SignIn() {
  return (
    <form
      action={async (formData) => {
        'use server';
        try {
          const res = await signIn('credentials', formData);
          console.log('hello world');
        } catch (e) {
          console.log('登录失败' + JSON.stringify(e));
        }
      }}
    >
      <label>
        Email
        <input name="email" />
      </label>
      <label>
        Password
        <input name="password" type="password" />
      </label>
      <button>Sign In</button>
    </form>
  );
}

点击登录,进入了 catch 块, 控制台报错:登录失败{"digest":"NEXT_REDIRECT;push;http://localhost:8080/login3;307;"}

这个错误信息表明 NextAuth 在尝试进行重定向操作,但在服务器组件或服务器操作中被捕获为错误。这是因为:

  1. 重定向被当作错误处理:在 Next.js 的服务器操作(Server Actions)中,重定向操作会被抛出为一个特殊类型的错误,这个错误包含了重定向的信息。
  2. 错误的本质:这不是真正的错误,而是 Next.js 内部用来处理重定向的机制。当你在 try/catch 块中捕获它时,它会被当作错误处理。
  3. 307 状态码:这是一个临时重定向状态码,表示请求应该使用另一个 URI 重新发出。

解决方案

这个问题的解决方法是告诉 NextAuth 不要在登录时自动重定向。通过以下方式修改代码:

import { signIn } from '@/auth';

export default function SignIn() {
  return (
    <form
      action={async (formData) => {
        'use server';
        try {
          // 添加 redirect: false 参数以防止自动重定向
          const res = await signIn('credentials', {
            redirect: false,
            email: formData.get('email'),
            password: formData.get('password')
          });
          console.log('登录结果', res);
        } catch (e) {
          console.log('登录失败' + JSON.stringify(e));
        }
      }}
    >
      <label>
        Email
        <input name="email" />
      </label>
      <label>
        Password
        <input name="password" type="password" />
      </label>
      <button>Sign In</button>
    </form>
  );
}

解释

  1. 添加 redirect: false 参数
    这告诉 NextAuth 不要在登录成功或失败后自动重定向,而是返回一个结果对象。
  2. 从 FormData 中提取字段
    使用
    formData.get('email')formData.get('password') 来明确提取表单中的字段,而不是直接传递整个 FormData 对象。
  3. 记录登录结果
    使用
    console.log('登录结果', res) 来记录登录的结果,这样可以看到登录是成功还是失败,以及返回的具体信息。

为什么会发生这个问题

在 Next.js 的服务器操作中,NextAuth 的 signIn 函数默认会在以下情况下尝试重定向:

  1. 登录成功时 - 重定向到成功页面或指定的回调 URL
  2. 登录失败时 - 重定向到错误页面或登录页面

但是,在服务器组件或服务器操作中,这种重定向会被作为一个特殊类型的错误抛出,因为服务器组件不能直接控制浏览器的导航。

通过设置 redirect: false,我们告诉 NextAuth 不要尝试重定向,而是简单地返回登录结果,这样我们就可以在代码中自己处理成功或失败的情况,而不会触发那个被捕获为错误的重定向操作。

现在,尝试登录时,应该不会再看到那个重定向错误,而是可以看到实际的登录结果,这样就可以根据结果来决定下一步操作。

本文通过 YUQUE WORDPRESS 同步自语雀

版权声明:
作者:东明兄
链接:https://blog.crazyming.com/note/3249/
来源:CrazyMing
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
海报
next-auth使用Credentials凭证登录报错
auth.ts: import NextAuth from 'next-auth'; import GitHub from 'next-auth/providers/github'; import Credentials from 'next-auth/providers/credentia……
<<上一篇
下一篇>>
chat