🤢

NextAuth.jsの認証失敗時にエラーメッセージを取得するための工夫

に公開4

Discussion

HiroakiHiroaki

export class UserNotFoundCredentialsSignin extends CredentialsSignin {
static CODE = 404;
constructor(console_message: string = 'User Not Found') {
super()
this.code = "404";
this.stack = undefined;
this.message = console_message;
}
}

自分もこの問題にぶち当たりましたが、上記のように拡張したエラーでthrowしたところ、コンソールのエラーstack部分が消えて1行だけになり、目障りではなくなりました。
this.messageはコンソール上だけのメッセージでクライアントには届きませんが、最悪codeの中に
${variable1}|${variable2}|${variable3}のようにすれば細かいデータもクライアント側で受け取れますね。

yukiyuki
authorize: async ({ email, password }) => {
        const inputEmail = email as string;
        const inputPassword = password as string;

  // サーバーサイドとのAPI
        const res = await login(inputEmail, inputPassword);
        if (res.status !== 200) {
          throw new Error(res.errorMessage); // ← ここでエラーメッセージを指定
        }
        if (!res?.data) {
          throw new Error(res.errorMessage);
        }

        if (!res.data.token) {
          throw new Error("Token is not found");
        }

        return {
          id: res.data.user.id,
          name: res.data.user.name,
          email: res.data.user.email,
          createdAt: res.data.user.createdAt,
          updatedAt: res.data.user.updatedAt,
          token: res.data.token,
        } as ExtendedUser;
      },

src/app/api/auth/[...nextauth].jsのauthorizeの中でthrow new Error("xxx")で指定した文字列は、以下のようにerror.cause?.err?.messageで取得できますね。

"use server";

import { AuthError } from "next-auth";

import { signIn as NextAuthSignIn } from "@/auth/auth";

export const signIn = async (email: string, password: string) => {
  try {
    await NextAuthSignIn("credentials", {
      email,
      password,
      redirect: false,
    });

    return {
      isSuccess: true,
      message: "ログインに成功しました。",
    };
  } catch (error) {
    if (error instanceof AuthError) {
      switch (error.type) {
        case "CredentialsSignin":
          return {
            isSuccess: false,
            error: {
              message: "メールアドレスまたはパスワードが間違っています。",
            },
          };
        case "CallbackRouteError":
          return {
            isSuccess: false,
            error: {
              message: error.cause?.err?.message, // ← ここ
            },
          };
        default:
          return {
            isSuccess: false,
            error: {
              message: "ログインに失敗しました。",
            },
          };
      }
    }
    return {
      isSuccess: false,
      error: {
        message: "ログインに失敗しました。",
      },
    };
  }
};