Return error information from API when using Next-auth
Asked Answered
C

2

8

Is it possible to allow next-auth to return errors from an API and pass them through from the client-side?

As an example, the API is returning specifically if the user's email or password is incorrect. On our mobile app, this is working great. Though on the website, we're using Next-auth. Using the credentials example from the documentation, it would be great to change the return value to an object.

import CredentialsProvider from "next-auth/providers/credentials"
providers: [
  CredentialsProvider({
    name: "Credentials",
 
    credentials: {
      username: { label: "Username", type: "text", placeholder: "jsmith" },
      password: {  label: "Password", type: "password" }
    },
    async authorize(credentials, req) {
      const user = { id: 1, name: "J Smith", email: "[email protected]" }

      if (user) {
        // Any object returned will be saved in `user` property of the JWT
        return user
      } else {
        // Return an object that will pass error information through to the client-side.
        return { errors: user.errors, status: false }
      }
    }
  })
]

Please do let me know if there is another post that relates to this one as I'm unable to find it online.

Chucklehead answered 28/1, 2022 at 16:54 Comment(0)
H
19

Yes this should allow you to do that, though in the credential, when passing the values to the next auth, add a redirect:false

You can find the documentation here

Your sign in method will therefore look like this.

signIn('credentials', { redirect: false, username:'username', password: 'password' })

Your code can look like this

import CredentialsProvider from "next-auth/providers/credentials"
providers: [
  CredentialsProvider({
    name: "Credentials",
 
    credentials: {
      username: { label: "Username", type: "text", placeholder: "jsmith" },
      password: {  label: "Password", type: "password" }
    },
    async authorize(credentials, req) {
      const user = { id: 1, name: "J Smith", email: "[email protected]" }

      if (user) {
        // Any object returned will be saved in `user` property of the JWT
        return user
      } else {
        // Return an object that will pass error information through to the client-side.
        throw new Error( JSON.stringify({ errors: user.errors, status: false }))
      }
    }
  })
Harrold answered 1/2, 2022 at 5:34 Comment(3)
This seems to have worked a treat. Thanks!Chucklehead
is there a better way?Lignite
Works like a charm. Thank you @obed-amoasiYabber
G
1

I managed to return the correct error information by using a promise with a catch statement in the authorize function:

export const authOptions: NextAuthOptions = {
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
  providers: [
    CredentialsProvider({
      name: "credentials",
      credentials: {
        email: {
          label: "Email",
          type: "email",
          placeholder: "[email protected]",
        },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials: any) {
        // console.log(credentials);
        const { user, jwt } = await axios
          .post(`http://localhost:1337/api/auth/local`, {
            identifier: credentials.email,
            password: credentials.password,
          })
          .then(({ data }) => {
            return data;
          })
          .catch((error) => {
            throw new Error(JSON.stringify(error.response.data));
          });

        return { jwt, ...user };
      },
    }),
  ],
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

The next-auth error is of type string, so you need to stringify it as JSON, then turn it back into an object from the client side.

Gwyn answered 24/6, 2023 at 21:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.