skip to Main Content

I am a beginner/intermediate developer attempting to create a NextJS 14 powered app for a friend of mine, but I seem to keep running into the same problem.

I am loosely following this tutorial by CodeWithAntonio with some slight tweaks to work for me. I have already tried going back through the tutorial more times than I can count to find a fix, but seemingly I cannot find one.

I am using NextJS 14 App-directory, with a Neon database and the Prisma adapter due to some incompatibilities with DrizzleORM in its current state.

This is my auth.ts file in the root directory:

import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";

import { db } from "@/lib/db";
import authConfig from "@/auth.config";
import { getUserById } from "@/lib/user";
import { UserRole } from "@prisma/client";

export const {
  handlers: { GET, POST },
  auth,
  signIn,
  signOut,
} = NextAuth({
  pages: {
    signIn: "/auth/login",
    error: "/auth/error",
  },
  callbacks: {
    async signIn({ user, account }) {
      if (account?.provider !== "credentials") return true;

      return true;
    },
    async session({ token, session }) {
      if (token.sub && session.user) {
        session.user.id = token.sub;
      }

      if (token.role && session.user) {
        session.user.role = token.role as UserRole;
      }

      return session;
    },
    async jwt({ token }) {
      if (!token.sub) return token;

      // this grabs the data from the db on the user from the user id on the token
      const existingUser = await getUserById(token.sub);

      if (!existingUser) return token;

      token.role = existingUser.role;

      return token;
    },
  },
  adapter: PrismaAdapter(db),
  session: { strategy: "jwt", maxAge: 60 * 60 * 24 },
  ...authConfig,
});

and this is my auth.config.ts file also in the root:

import bcrypt from "bcryptjs";

import type { NextAuthConfig } from "next-auth";
import Credentials from "next-auth/providers/credentials";

import { LoginSchema } from "@/schemas";
import { getUserByEmail } from "./lib/user";

export default {
  providers: [
    Credentials({
      async authorize(credentials) {
        const validatedFields = LoginSchema.safeParse(credentials);

        if (validatedFields.success) {
          const { email, password } = validatedFields.data;

          // gets the user data from the db by email
          const user = await getUserByEmail(email);

          if (!user || !user.password) return null;

          const passwordsMatch = await bcrypt.compare(password, user.password);

          if (passwordsMatch) return user;

          return null;
        }

        return null;
      },
    }),
  ],
} satisfies NextAuthConfig;

I believe these are all the files useful to the error which looks like this for context:

Read more at https://errors.authjs.dev/#credentialssignin
[auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: Error
    at Module.callback (webpack-internal:///(action-browser)/./node_modules/@auth/core/lib/actions/callback/index.js:226:23)
    at async AuthInternal (webpack-internal:///(action-browser)/./node_modules/@auth/core/lib/index.js:66:24)
    at async Auth (webpack-internal:///(action-browser)/./node_modules/@auth/core/index.js:126:34)
    at async signIn (webpack-internal:///(action-browser)/./node_modules/next-auth/lib/actions.js:51:17)
    at async $$ACTION_0 (webpack-internal:///(action-browser)/./actions/login.ts:46:9)
    at async F:lng-v3node_modulesnextdistcompilednext-serverapp-page.runtime.dev.js:39:418
    at async rw (F:lng-v3node_modulesnextdistcompilednext-serverapp-page.runtime.dev.js:38:7978)
    at async r4 (F:lng-v3node_modulesnextdistcompilednext-serverapp-page.runtime.dev.js:41:1251)
    at async doRender (F:lng-v3node_modulesnextdistserverbase-server.js:1438:30)
    at async cacheEntry.responseCache.get.routeKind (F:lng-v3node_modulesnextdistserverbase-server.js:1599:28)
    at async DevServer.renderToResponseWithComponentsImpl (F:lng-v3node_modulesnextdistserverbase-server.js:1507:28)
    at async DevServer.renderPageComponent (F:lng-v3node_modulesnextdistserverbase-server.js:1931:24)
    at async DevServer.renderToResponseImpl (F:lng-v3node_modulesnextdistserverbase-server.js:1969:32)
    at async DevServer.pipeImpl (F:lng-v3node_modulesnextdistserverbase-server.js:920:25)
    at async NextNodeServer.handleCatchallRenderRequest (F:lng-v3node_modulesnextdistservernext-server.js:272:17)
    at async DevServer.handleRequestImpl (F:lng-v3node_modulesnextdistserverbase-server.js:816:17)
    at async F:lng-v3node_modulesnextdistserverdevnext-dev-server.js:339:20
    at async Span.traceAsyncFn (F:lng-v3node_modulesnextdisttracetrace.js:154:20)
    at async DevServer.handleRequest (F:lng-v3node_modulesnextdistserverdevnext-dev-server.js:336:24)
    at async invokeRender (F:lng-v3node_modulesnextdistserverlibrouter-server.js:174:21)
    at async handleRequest (F:lng-v3node_modulesnextdistserverlibrouter-server.js:353:24)
    at async requestHandlerImpl (F:lng-v3node_modulesnextdistserverlibrouter-server.js:377:13)
    at async Server.requestListener (F:lng-v3node_modulesnextdistserverlibstart-server.js:141:13)
[auth][details]: {
  "provider": "credentials"
}

This is the server action (login.ts) that actually logs the user in and is called directly from the login form:

"use server";

import * as z from "zod";

import { LoginSchema } from "@/schemas";
import { signIn } from "@/auth";
import { DEFAULT_LOGIN_REDIRECT } from "@/routes";
import { AuthError } from "next-auth";
import { getUserByEmail } from "@/lib/user";
import { generateVerificationToken } from "@/lib/tokens";

export const login = async (values: z.infer<typeof LoginSchema>) => {
  const validatedFields = LoginSchema.safeParse(values);

  if (!validatedFields.success) {
    return { error: "Invalid fields!" };
  }

  const { email, password } = validatedFields.data;

  // gets user data from the db by email
  const existingUser = await getUserByEmail(email);

  if (!existingUser || !existingUser.email || !existingUser.password) {
    return { error: "Your email and/or password are incorrect." };
  }

  if (!existingUser.email_verified) {
    // creates and returns a verification token for the user from the db
    const verificationToken = await generateVerificationToken(
      existingUser.email
    );

    return { success: "Verification email sent!" };
  }

  try {
    await signIn("credentials", {
      email,
      password,
      // currently just set to /settings page
      redirectTo: DEFAULT_LOGIN_REDIRECT,
    });
  } catch (error) {
    // this is what seems to be returning the error message "CallbackRouteError"
    console.log(error);
    if (error instanceof AuthError) {
      switch (error.type) {
        case "CredentialsSignin":
          return { error: "Your email and/or password are incorrect." };
        default:
          return { error: "Something went wrong!" };
      }
    }
    throw error;
  }
};

When using the signIn() function through the server action (login.ts) in my login form passing the email and password in string format, I get an error console logged saying:

Read more at https://errors.authjs.dev/#credentialssignin
[auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: Error
    at Module.callback (webpack-internal:///(action-browser)/./node_modules/@auth/core/lib/actions/callback/index.js:226:23)
    at async AuthInternal (webpack-internal:///(action-browser)/./node_modules/@auth/core/lib/index.js:66:24)
    at async Auth (webpack-internal:///(action-browser)/./node_modules/@auth/core/index.js:126:34)
    at async signIn (webpack-internal:///(action-browser)/./node_modules/next-auth/lib/actions.js:51:17)
    at async $$ACTION_0 (webpack-internal:///(action-browser)/./actions/login.ts:46:9)
    at async F:lng-v3node_modulesnextdistcompilednext-serverapp-page.runtime.dev.js:39:418
    at async rw (F:lng-v3node_modulesnextdistcompilednext-serverapp-page.runtime.dev.js:38:7978)
    at async r4 (F:lng-v3node_modulesnextdistcompilednext-serverapp-page.runtime.dev.js:41:1251)
    at async doRender (F:lng-v3node_modulesnextdistserverbase-server.js:1438:30)
    at async cacheEntry.responseCache.get.routeKind (F:lng-v3node_modulesnextdistserverbase-server.js:1599:28)
    at async DevServer.renderToResponseWithComponentsImpl (F:lng-v3node_modulesnextdistserverbase-server.js:1507:28)
    at async DevServer.renderPageComponent (F:lng-v3node_modulesnextdistserverbase-server.js:1931:24)
    at async DevServer.renderToResponseImpl (F:lng-v3node_modulesnextdistserverbase-server.js:1969:32)
    at async DevServer.pipeImpl (F:lng-v3node_modulesnextdistserverbase-server.js:920:25)
    at async NextNodeServer.handleCatchallRenderRequest (F:lng-v3node_modulesnextdistservernext-server.js:272:17)
    at async DevServer.handleRequestImpl (F:lng-v3node_modulesnextdistserverbase-server.js:816:17)
    at async F:lng-v3node_modulesnextdistserverdevnext-dev-server.js:339:20
    at async Span.traceAsyncFn (F:lng-v3node_modulesnextdisttracetrace.js:154:20)
    at async DevServer.handleRequest (F:lng-v3node_modulesnextdistserverdevnext-dev-server.js:336:24)
    at async invokeRender (F:lng-v3node_modulesnextdistserverlibrouter-server.js:174:21)
    at async handleRequest (F:lng-v3node_modulesnextdistserverlibrouter-server.js:353:24)
    at async requestHandlerImpl (F:lng-v3node_modulesnextdistserverlibrouter-server.js:377:13)
    at async Server.requestListener (F:lng-v3node_modulesnextdistserverlibstart-server.js:141:13)
[auth][details]: {
  "provider": "credentials"
}

If you need any more info just let me know 🙂

I truly do apologise if this is a simple stupid mistake but are incredibly grateful to anyone who can offer help!

Many thanks,
Louis

2

Answers


  1. I have also this problem [auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror
    [auth][cause]: Error
    at Module.callback (webpack-internal:///(action-browser)/./node_modules/next-auth/node_modules/@auth/core/lib/actions/callback/index.js:226:23)

    Login or Signup to reply.
  2. This is my code and it is working
    
    **Credential Provider**
    
    export default {
        providers: [
            Credentials({
                async authorize(credentials) {
                    const validatedFields = loginSchema.safeParse(credentials);
    
                    if (validatedFields.success) {
                        const { email, password } = validatedFields.data;
    
                        const user = await getUserByEmail(email);
                        if (!user || !user.password) return null;
    
                        const passwordMatches = await bcrypt.compare(
                            password,
                            user.password
                        );
    
                        if (passwordMatches) return user;
                    }
    
                    return null;
                }
            })
        ]
    } satisfies NextAuthConfig
    
    **Login Action**
    
    "use server"
    import { getUserByEmail } from '@/data/user';
    import { DEFAULT_LOGIN_REDIRECT } from './../routes/routes';
    import { signIn } from "@/lib/auth"
    import { loginSchema } from "@/schemas"
    import { AuthError } from 'next-auth';
    import * as z from "zod"
    
    export const login = async (values: z.infer<typeof loginSchema>) => {
        const validatedFields = loginSchema.safeParse(values);
    
        if (!validatedFields.success) {
            return { error: "Invalid fields!" }
        }
    
        const { email, password } = validatedFields.data;
    
        const existingUser = await getUserByEmail(email);
    
    
        if (!existingUser || !existingUser.email) {
            return { error: "Invalid credentials!" }
        }
    
        try {
            await signIn("credentials", {
                email,
                password,
                redirectTo: DEFAULT_LOGIN_REDIRECT,
            })
        } catch (error) {
            if (error instanceof AuthError) {
                switch (error.type) {
                    case "CredentialsSignin":
                        return { error: "Invalid credentials!" }
                    default:
                        return { error: "Something went wrong!" }
                }
            }
    
            throw error
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search