Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot return custom error to the client side in the Next-Auth v5 Credentials Auth #11190

Closed
dsmabulage opened this issue Jun 17, 2024 · 12 comments
Labels
bug Something isn't working providers triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@dsmabulage
Copy link

Provider type

Credentials

Environment

 "next": "14.2.3",
 "next-auth": "^5.0.0-beta.19",

Reproduction URL

https://github.com/dsmabulage/inventes

Describe the issue

I'm trying to implement the email, password login in the next app using next-auth v5.

In the NextAuth function inside authorize, I tried various methods to throw a custom error message that can passed to the user to show what's going wrong with the credentials.

How to reproduce

export const { auth, handlers, signIn, signOut } = NextAuth({
  session: {
    strategy: 'jwt',
  },
  pages: {
    signIn: '/auth/login',
  },
  providers: [
    CredentialsProvider({
      credentials: {
        email: {},
        password: {},
      },
      async authorize({ email, password }) {
        try {
          throw new Error(
            JSON.stringify({ errors: 'user.errors', status: false })
          );
        } catch (error) {
          throw new Error(
            JSON.stringify({ errors: ' catch user.errors', status: false })
          );
        }
      },
    }),
  ],

Expected behavior

I want to get that error message to the client side and show that error message to the user.

@dsmabulage dsmabulage added bug Something isn't working providers triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Jun 17, 2024
@hezean
Copy link

hezean commented Jun 18, 2024

Hi, I'm facing the same problem. I found this temporary solution that may be helpful: #9900 (comment).

@Ali-Raza764
Copy link

The same issue is being discussed here in detail. I might also tell you that there is a way to check for some error but that also seems to broken currently In previous versions you could do something like this:

import { AuthError } from "next-auth";
import { signIn } from "next-auth/react";
    try {
      setLoading(true);
      setError("");
      const res = await signIn("credentials", {
        redirect: false,
        email,
        password,
      });

      //* The res here has no credentials data only error:true or error:null so we can manage the state based on that
      //* Next auth does not send the data due to security reasons
      if (res.error === null) {
        router.push("/protected");
      }
      if (res.error) {
        setError("Check Your Email Or Password");
      }
    } catch (error) {
      console.error(error.message);
      if (error instanceof AuthError) {
        switch (error.type) {
          case "CredentialsSignin":
            console.log("Invalid Password");
            setError("Please Check Your Password")
          default:
            console.log("Something went wrong");
            setError("Something went wrong")
        }
      }
    } finally {
      setLoading(false);
    }
  };

The issue with this approach that you do not know if the error is related to credentials like invalid email or something like database connection timeout

@dsmabulage
Copy link
Author

The same issue is being discussed here in detail. I might also tell you that there is a way to check for some error but that also seems to broken currently In previous versions you could do something like this:

import { AuthError } from "next-auth";
import { signIn } from "next-auth/react";
    try {
      setLoading(true);
      setError("");
      const res = await signIn("credentials", {
        redirect: false,
        email,
        password,
      });

      //* The res here has no credentials data only error:true or error:null so we can manage the state based on that
      //* Next auth does not send the data due to security reasons
      if (res.error === null) {
        router.push("/protected");
      }
      if (res.error) {
        setError("Check Your Email Or Password");
      }
    } catch (error) {
      console.error(error.message);
      if (error instanceof AuthError) {
        switch (error.type) {
          case "CredentialsSignin":
            console.log("Invalid Password");
            setError("Please Check Your Password")
          default:
            console.log("Something went wrong");
            setError("Something went wrong")
        }
      }
    } finally {
      setLoading(false);
    }
  };

The issue with this approach that you do not know if the error is related to credentials like invalid email or something like database connection timeout

Is there a way to throw a custom error message from the authorize method because I have another validation more than checking only the username and password? So that case I need to show different error messages to the client.

@Ali-Raza764
Copy link

we can customize the authorize() function to return custom errors like this #9871
And here #9099
But to be honest I am not sure how to implement these.

@douwepausma
Copy link

I read somewhere one should be able to throw a new Error with a custom code property (e.g. {code: 'Not verified.'}) and it will be passed to the client. However in 5.0.0-beta.19 it will always return null, {error: 'Configuration', code: null, status: 200, ok: true, url: null}

@dsmabulage
Copy link
Author

I read somewhere one should be able to throw a new Error with a custom code property (e.g. {code: 'Not verified.'}) and it will be passed to the client. However in 5.0.0-beta.19 it will always return null, {error: 'Configuration', code: null, status: 200, ok: true, url: null}

always return null, is it a next-auth issue

@Ali-Raza764
Copy link

#11074 (comment) Follow here for discussions.

@RuentDev
Copy link

RuentDev commented Jul 6, 2024

Same here I always get these return object even I explicity return an error

image

image

@Ali-Raza764
Copy link

#11074 (comment) Please follow this issue for details

@OlushesiToheeb
Copy link

This is how i was able to revolve this

In auth.ts or auth.config.ts

create a class that extend theAuthError class

class InvalidLoginError extends AuthError {
  code = 'custom';
  errorMessage: string;
  constructor(message?: any, errorOptions?: any) {
    super(message, errorOptions);
    this.errorMessage = message;
  }
}

then in your credential provider you can use it like

providers: [
    Credentials({
      async authorize(credentials) {
        try {
          const response = await axios.post('your-endpoint', {
            phone: credentials?.phone,
            password: credentials?.password,
          });
          if (response.data.error) {
            throw new InvalidLoginError(response.data.error);
          }

          const user = response?.data?.data;
          if (user) {
            return user;
          } else {
            return null;
          }
        } catch (e: any) {
          throw new InvalidLoginError(e.response?.data?.message);
        }
      },
    }),
  ],

with this, you can catch the error in your signin api route and also your client signin component

@aaliboyev
Copy link

I was able to fix this problem check out in discussions #8999 (comment)

@balazsorban44
Copy link
Member

Fixed in #11469

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working providers triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

No branches or pull requests

8 participants