Next.js Discord

Discord Forum

Build Warning Need Explanation Please

Answered
Russian Blue posted this in #help-forum
Open in Discord
Russian BlueOP
$ npm run build

> tuddle@0.1.0 build
> next build

   â–² Next.js 14.0.4
   - Environments: .env

 âš  Compiled with warnings

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (process.nextTick at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.config.ts

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (setImmediate at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.config.ts

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (setImmediate at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.config.ts

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (process.nextTick at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.config.ts
Answered by Ray
look like the error is caused by bcrypt usage in middleware.
auth.config.ts should only contain the callback.authorized and move everything else to auth.ts
View full answer

126 Replies

Russian BlueOP
Other part of the log:
✓ Linting and checking validity of types
 ✓ Collecting page data    
 ✓ Generating static pages (15/15)
 ✓ Collecting build traces    
 ✓ Finalizing page optimization

   Creating an optimized production build  .Route (app)                              Size     First Load JS
┌ λ /                                    175 B          88.9 kB
├ λ /_not-found                          0 B                0 B
├ λ /admin/dashboard                     156 B          82.1 kB
├ λ /api/auth/[...nextauth]              0 B                0 B
├ λ /auth/error                          1.01 kB        97.6 kB
├ λ /auth/login                          2.1 kB          128 kB
├ λ /auth/new-password                   1.95 kB         128 kB
├ λ /auth/new-verification               1.76 kB         106 kB
├ λ /auth/register                       1.99 kB         128 kB
├ λ /auth/reset                          1.92 kB         128 kB
├ λ /newTask                             2.12 kB         121 kB
├ λ /settings                            156 B          82.1 kB
├ λ /tasks                               2.24 kB        91.8 kB
└ λ /tasks/[id]                          156 B          82.1 kB
+ First Load JS shared by all            81.9 kB
  ├ chunks/938-5c77385e180c055e.js       26.7 kB
  ├ chunks/fd9d1056-de8ef4a71b9a5d7e.js  53.3 kB
  ├ chunks/main-app-08665501bc173b02.js  220 B
  â”” chunks/webpack-49b0bf3aa3ac2455.js   1.74 kB


Æ’ Middleware                             188 kB (red)

λ  (Dynamic)  server-rendered on demand using Node.js
Answer
Russian BlueOP
my auth.config.ts:
import type { NextAuthConfig } from "next-auth";
import Google from "next-auth/providers/google";
import Credentials from "next-auth/providers/credentials";
import { LoginSchema } from "./schemas";
import { getUserByEmail } from "./data/user";
import bcrypt from "bcryptjs";
export default {
  providers: [
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    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 passwordsMatch = await bcrypt.compare(password, user.password);

          if (passwordsMatch) return user;
        }
        return null;
      },
    }),
  ],
} satisfies NextAuthConfig;
my auth.ts:
import NextAuth, { Account, Session, User } from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
// import { PrismaClient } from "@prisma/client";
import authConfig from "./auth.config";
import db from "./lib/db";
import { JWT } from "next-auth/jwt";
import { getUserById } from "./data/user";
import { getAccountByUserId } from "./data/account";
// const prisma = new PrismaClient();

export const {
  handlers: { GET, POST },
  auth,
  signIn,
  signOut,
} = NextAuth({
  pages: {
    signIn: "/auth/login",
    error: "/auth/error",
  },
  events: {
    //events are called when a certain callback is performed
    //for example linkAccount is called when a user creates an account using a provider other than credentials provider
    async linkAccount({ user }) {
      // automatically verify users logging in with google
      await db.user.update({
        where: { id: user.id },
        data: { emailVerified: new Date() },
      });
    },
  },
  callbacks: {
    async signIn({ user, account }) {

      if (account?.provider !== "credentials") return true;

      if (!user || !user.id) return false;
      const existingUser = await getUserById(user.id);

      if (!existingUser?.emailVerified) return false
      return true;
    },
    async session(args) {
      const { session, token } = args as { session: Session; token: JWT };

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

      const existingUser = await getUserById(token.sub);
      if (!existingUser) return token;
    
      return token;
    },
  },
  adapter: PrismaAdapter(db), //prisma
  session: { strategy: "jwt" },
  ...authConfig,
});
@Russian Blue import NextAuth, { Account, Session, User } from "next-auth"; import { PrismaAdapter } from "@auth/prisma-adapter"; // import { PrismaClient } from "@prisma/client"; import authConfig from "./auth.config"; import db from "./lib/db"; import { JWT } from "next-auth/jwt"; import { getUserById } from "./data/user"; import { getAccountByUserId } from "./data/account"; // const prisma = new PrismaClient(); export const { handlers: { GET, POST }, auth, signIn, signOut, } = NextAuth({ pages: { signIn: "/auth/login", error: "/auth/error", }, events: { //events are called when a certain callback is performed //for example linkAccount is called when a user creates an account using a provider other than credentials provider async linkAccount({ user }) { // automatically verify users logging in with google await db.user.update({ where: { id: user.id }, data: { emailVerified: new Date() }, }); }, }, callbacks: { async signIn({ user, account }) { if (account?.provider !== "credentials") return true; if (!user || !user.id) return false; const existingUser = await getUserById(user.id); if (!existingUser?.emailVerified) return false return true; }, async session(args) { const { session, token } = args as { session: Session; token: JWT }; return session; }, async jwt({ token, user }) { if (!token.sub) return token; const existingUser = await getUserById(token.sub); if (!existingUser) return token; return token; }, }, adapter: PrismaAdapter(db), //prisma session: { strategy: "jwt" }, ...authConfig, });
yes, move callbacks to auth.config.ts
and move providers to auth.ts
Russian BlueOP
Is there a guide I can follow because I am getting typescript errors
@Russian Blue Is there a guide I can follow because I am getting typescript errors
set empty array for providers in auth.ts
NextAuth({
  providers: [],
  ......other thing,
  ...authConfig
})
Russian BlueOP
Okay I had to remove it form auth.config for the error to go, then? How to move callbacks to auth.config
to be honest I followed an online tutorial on youtube to implement this, but I am not sure if the tutorial itself is wrong
Russian BlueOP
@Russian Blue Click to see attachment
set it empty array
then this in auth.ts
NextAuth({
  ...authConfig,
  providers: [...your providers]
  ......other thing,
})
@Ray set it empty array
Russian BlueOP
but it is an object in the github example you sent
Russian BlueOP
oh so I have providers in both files
but an empty arrya in the auth config file
yea
Russian BlueOP
I just have errors in this:
which leads to errors in the auth file
Argument of type '{ providers: (OAuthConfig<any> | CredentialsConfig<Record<string, CredentialInput>>)[]; pages: { signIn: string; error: string; }; callbacks: { ...; }; }' is not assignable to parameter of type 'NextAuthConfig | ((request: Request | undefined) => NextAuthConfig)'.
  Type '{ providers: (OAuthConfig<any> | CredentialsConfig<Record<string, CredentialInput>>)[]; pages: { signIn: string; error: string; }; callbacks: { ...; }; }' is not assignable to type 'NextAuthConfig'.
    Types of property 'callbacks' are incompatible.
      Type '{ signIn({ user, account }: { user: User | AdapterUser; account: Account | null; profile?: Profile | undefined; email?: { verificationRequest?: boolean | undefined; } | undefined; credentials?: Record<...> | undefined; }): Promise<...>; session(args: ({ ...; } | { ...; }) & { ...; }): Promise<...>; jwt({ token, user...' is not assignable to type 'Partial<CallbacksOptions<Profile, Account>> & { authorized?: ((params: { request: NextRequest; auth: Session | null; }) => Awaitable<...>) | undefined; }'.
        Type '{ signIn({ user, account }: { user: User | AdapterUser; account: Account | null; profile?: Profile | undefined; email?: { verificationRequest?: boolean | undefined; } | undefined; credentials?: Record<...> | undefined; }): Promise<...>; session(args: ({ ...; } | { ...; }) & { ...; }): Promise<...>; jwt({ token, user...' is not assignable to type 'Partial<CallbacksOptions<Profile, Account>>'.
          The types returned by 'session(...)' are incompatible between these types.
            Type 'Promise<Session>' is not assignable to type 'Awaitable<Session | DefaultSession>'.
              Type 'Promise<Session>' is not assignable to type 'PromiseLike<Session | DefaultSession>'.ts(2345)
@Russian Blue Argument of type '{ providers: (OAuthConfig<any> | CredentialsConfig<Record<string, CredentialInput>>)[]; pages: { signIn: string; error: string; }; callbacks: { ...; }; }' is not assignable to parameter of type 'NextAuthConfig | ((request: Request | undefined) => NextAuthConfig)'. Type '{ providers: (OAuthConfig<any> | CredentialsConfig<Record<string, CredentialInput>>)[]; pages: { signIn: string; error: string; }; callbacks: { ...; }; }' is not assignable to type 'NextAuthConfig'. Types of property 'callbacks' are incompatible. Type '{ signIn({ user, account }: { user: User | AdapterUser; account: Account | null; profile?: Profile | undefined; email?: { verificationRequest?: boolean | undefined; } | undefined; credentials?: Record<...> | undefined; }): Promise<...>; session(args: ({ ...; } | { ...; }) & { ...; }): Promise<...>; jwt({ token, user...' is not assignable to type 'Partial<CallbacksOptions<Profile, Account>> & { authorized?: ((params: { request: NextRequest; auth: Session | null; }) => Awaitable<...>) | undefined; }'. Type '{ signIn({ user, account }: { user: User | AdapterUser; account: Account | null; profile?: Profile | undefined; email?: { verificationRequest?: boolean | undefined; } | undefined; credentials?: Record<...> | undefined; }): Promise<...>; session(args: ({ ...; } | { ...; }) & { ...; }): Promise<...>; jwt({ token, user...' is not assignable to type 'Partial<CallbacksOptions<Profile, Account>>'. The types returned by 'session(...)' are incompatible between these types. Type 'Promise<Session>' is not assignable to type 'Awaitable<Session | DefaultSession>'. Type 'Promise<Session>' is not assignable to type 'PromiseLike<Session | DefaultSession>'.ts(2345)
where is your session type and jwt type coming from
I think you don't need to cast it manually
Russian BlueOP
oh i was importing the Session type from wrong package
you were right
If I dont add the type casting I have this error:
I put these in auth or auth.config:
@Ray https://authjs.dev/getting-started/typescript
check this guide
Russian BlueOP
I tried to follow the guide as much as possible however error remains. Here is the final version of the files with no errors.
auth.cofig.ts:
Russian BlueOP
export const authConfig = {
  pages: {
    signIn: "/auth/login"
  },
  providers: [],
  callbacks: {
    async signIn({ user, account }) {
   
      if (account?.provider !== "credentials") return true;

      if (!user || !user.id) return false;
      const existingUser = await getUserById(user.id);


      if (!existingUser?.emailVerified) return false;
    },
    async session(args) {
      const { session, token } = args as { session: Session; token: JWT };

      if (token.sub && session.user) {
        session.user.id = token.sub;
      }
      if (token.role && session.user) {
        session.user.role = token.role; //user.role
      }
      if (session.user) {
        session.user.name = token.name;
        session.user.email = token.email;
        session.user.isOAuth = token.isOAuth as boolean;
      }
      return session;
    },
    async jwt({ token, user }) {
      if (!token.sub) return token;
      // if (user) token.role = user.role;

      const existingUser = await getUserById(token.sub);
      if (!existingUser) return token;
      const existingAccount = await getAccountByUserId(existingUser.id);
      token.isOAuth = !!existingAccount;
      token.name = existingUser.name;
  
      return token;
    },
  },

  session: { strategy: "jwt" },
} satisfies NextAuthConfig;

/**
 *   callbacks: {
    async signIn({ user, account }) {
      // ALlow Oauth without email verification
      if (account?.provider !== "credentials") return true;

   
      return true;
    },
    async session(args) {
      const { session, token } = args as { session: Session; token: JWT };

      if (token.sub && session.user) {
        session.user.id = 
      }
   
      return session;
    },
    async jwt({ token, user }) {
      if (!token.sub)
      // if (user) token.role = 

      const existingUser = 
      if (!existingUser)
      const existingAccount =
      token.isOAuth =
      token.name 
      token.email 
      return token;
    },
  },
 */
auth.ts"
import NextAuth, { Account, Session, User } from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
// import { PrismaClient } from "@prisma/client";

import db from "./lib/db";
import { JWT } from "next-auth/jwt";
import { getUserByEmail, getUserById } from "./data/user";
import { getAccountByUserId } from "./data/account";
import { authConfig } from "./auth.config";
import bcrypt from "bcryptjs";
import Google from "next-auth/providers/google";
import Credentials from "next-auth/providers/credentials";
import { LoginSchema } from "./schemas";
// const prisma = new PrismaClient();

export const {
  handlers: { GET, POST },
  auth,
  signIn,
  signOut,
} = NextAuth({
  ...authConfig,
  providers: [
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    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 passwordsMatch = await bcrypt.compare(password, user.password);
          if (passwordsMatch) return user;
        }
        return null;
      },
    }),
  ],

  // ...authConfig,
});
@Russian Blue export const authConfig = { pages: { signIn: "/auth/login" }, providers: [], callbacks: { async signIn({ user, account }) { if (account?.provider !== "credentials") return true; if (!user || !user.id) return false; const existingUser = await getUserById(user.id); if (!existingUser?.emailVerified) return false; }, async session(args) { const { session, token } = args as { session: Session; token: JWT }; if (token.sub && session.user) { session.user.id = token.sub; } if (token.role && session.user) { session.user.role = token.role; //user.role } if (session.user) { session.user.name = token.name; session.user.email = token.email; session.user.isOAuth = token.isOAuth as boolean; } return session; }, async jwt({ token, user }) { if (!token.sub) return token; // if (user) token.role = user.role; const existingUser = await getUserById(token.sub); if (!existingUser) return token; const existingAccount = await getAccountByUserId(existingUser.id); token.isOAuth = !!existingAccount; token.name = existingUser.name; return token; }, }, session: { strategy: "jwt" }, } satisfies NextAuthConfig; /** * callbacks: { async signIn({ user, account }) { // ALlow Oauth without email verification if (account?.provider !== "credentials") return true; return true; }, async session(args) { const { session, token } = args as { session: Session; token: JWT }; if (token.sub && session.user) { session.user.id = } return session; }, async jwt({ token, user }) { if (!token.sub) // if (user) token.role = const existingUser = if (!existingUser) const existingAccount = token.isOAuth = token.name token.email return token; }, }, */
does your error look like this?
Russian BlueOP
yes it is a public issue on their github
@Russian Blue yes it is a public issue on their github
yeah downgrade for now
Russian BlueOP
I am using this workaround to solve it for now
Russian BlueOP
and here are my types:
import { UserRole } from "@prisma/client";
import { DefaultSession } from "next-auth";

export type ExtendedUser = DefaultSession["user"] & {
  role: UserRole;
  isOAuth: boolean;
};

declare module "next-auth" {
  // interface User {
  //   role: Userrole;
  //   // isOAuth: boolean;
  // }
  interface Session {
    user: ExtendedUser;
  }
}

import { JWT } from "@auth/core/jwt";

declare module "@auth/core/jwt" {
  interface JWT {
    role?: UserRole;
  }
}
Russian BlueOP
should I try to run build now
@Russian Blue should I try to run build now
go ahead!
Russian BlueOP
âš  Compiled with warnings

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (process.nextTick at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.ts
./lib/auth.ts

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (setImmediate at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.ts
./lib/auth.ts

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (setImmediate at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.ts
./lib/auth.ts

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (process.nextTick at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.ts
./lib/auth.ts
Russian BlueOP
import { authConfig } from "./auth.config";
import NextAuth from "next-auth";
const { auth } = NextAuth(authConfig);
import {
  DEFAULT_LOGIN_REDIRECT,
  publicRoutes,
  authRoutes,
  apiAuthPrefix,
  adminPrefix,
} from "./routes";
import { currentUser } from "./lib/auth";
import { UserRole } from "@prisma/client";
export default auth(async (req) => {
  const { nextUrl } = req;
  const isLoggedIn = !!req.auth;

  const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix);
  const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix);
  if (isAdminRoute) {
    const user = await currentUser();
    if (user?.role !== UserRole.ADMIN) return false; //TODO: make sure this is best way
  }
  const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
  const isAuthRoute = authRoutes.includes(nextUrl.pathname);

  if (isApiAuthRoute) return null;

  if (isAuthRoute) {
    if (isLoggedIn) {
      return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
    }
    return null;
  }
  if (!isLoggedIn && !isPublicRoute) {
    return Response.redirect(new URL("/auth/login", nextUrl));
  }
  return null;
});

// Optionally, don't invoke Middleware on some paths
export const config = {
  matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"], //routes that match this regex will invoke this middleware
};
then make your middleware look like this
import NextAuth from 'next-auth';
import { authConfig } from './auth.config';

export default NextAuth(authConfig).auth;

export const config = {
  // https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
};
Russian BlueOP
in the authorized callback?
@Russian Blue in the authorized callback?
it give you the user object
Russian BlueOP
okay fixed it up, but still same warning
âš  Compiled with warnings

./node_modules/bcryptjs/dist/bcrypt.js
A Node.js API is used (process.nextTick at line: 274) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime

Import trace for requested module:
./node_modules/bcryptjs/dist/bcrypt.js
./auth.ts
./lib/auth.ts
./auth.config.ts
Russian BlueOP
auth.config ^
middleware:import { authConfig } from "./auth.config";
import NextAuth from "next-auth";

export default NextAuth(authConfig).auth;

// Optionally, don't invoke Middleware on some paths
export const config = {
matcher: ["/((?!.+\.[\w]+$|_next).)", "/", "/(api|trpc)(.)"], //routes that match this regex will invoke this middleware
};
ok move callback.signIn, callback.session, callback.jwt to auth.ts
NextAuth({
  ...authConfig,
  providers: [...your providers],
  callbacks: {
    your callback,
    ...authConfig.callbacks
  }
})

then change your auth.ts like this
Russian BlueOP
still the same error, sorry for taking up your time
could you show the code again
Russian BlueOP
auth.config:
export const authConfig = {
  pages: {
    signIn: "/auth/login",
    error: "/auth/error",
  },
  providers: [],
  callbacks: {
    async authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = auth;

      const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix);
      const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix);
      if (isAdminRoute) {
        const user = await currentUser();
        if (user?.role !== UserRole.ADMIN) return false; //TODO: make sure this is best way
      }
      const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
      const isAuthRoute = authRoutes.includes(nextUrl.pathname);

      if (isApiAuthRoute) return false;

      if (isAuthRoute) {
        if (isLoggedIn) {
          return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
        }
      }
      if (!isLoggedIn && !isPublicRoute) {
        return Response.redirect(new URL("/auth/login", nextUrl));
      }
      return true;
    },
  },

  events: {
    //events are called when a certain callback is performed
    //for example linkAccount is called when a user creates an account using a provider other than credentials provider
    async linkAccount({ user }) {
      // automatically verify users logging in with google
      await db.user.update({
        where: { id: user.id },
        data: { emailVerified: new Date() },
      });
    },
  },

  adapter: PrismaAdapter(db), //prisma
  session: { strategy: "jwt" },
} satisfies NextAuthConfig;
middleware:
import { authConfig } from "./auth.config";
import NextAuth from "next-auth";

export default NextAuth(authConfig).auth;

// Optionally, don't invoke Middleware on some paths
export const config = {
  matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"], //routes that match this regex will invoke this middleware
};
Russian BlueOP
auth:
move everthing to auth.ts except pages, providers and callbacks.authorized
auth.config.ts is going to get imported to middleware so it need to be clean, no any node api stuff
Russian BlueOP
okay I moved even adapter and session to auth.config + events
Russian BlueOP
still same error, what does it mean nodejs api?
wait, it only show error when building?
nm i see another error
Russian BlueOP
I see this now in dev
@Russian Blue export const authConfig = { pages: { signIn: "/auth/login", error: "/auth/error", }, providers: [], callbacks: { async authorized({ auth, request: { nextUrl } }) { const isLoggedIn = auth; const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix); const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix); if (isAdminRoute) { const user = await currentUser(); if (user?.role !== UserRole.ADMIN) return false; //TODO: make sure this is best way } const isPublicRoute = publicRoutes.includes(nextUrl.pathname); const isAuthRoute = authRoutes.includes(nextUrl.pathname); if (isApiAuthRoute) return false; if (isAuthRoute) { if (isLoggedIn) { return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl)); } } if (!isLoggedIn && !isPublicRoute) { return Response.redirect(new URL("/auth/login", nextUrl)); } return true; }, }, events: { //events are called when a certain callback is performed //for example linkAccount is called when a user creates an account using a provider other than credentials provider async linkAccount({ user }) { // automatically verify users logging in with google await db.user.update({ where: { id: user.id }, data: { emailVerified: new Date() }, }); }, }, adapter: PrismaAdapter(db), //prisma session: { strategy: "jwt" }, } satisfies NextAuthConfig;
async authorized({ auth, request: { nextUrl } }) {
  const isLoggedIn = !!auth?.user;

  const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix);
  const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix);
  if (isAdminRoute) {
    const user = auth?.user
    if (user?.role !== UserRole.ADMIN) return false; //TODO: make sure this is best way
  }
  const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
  const isAuthRoute = authRoutes.includes(nextUrl.pathname);

  if (isApiAuthRoute) return false;

  if (isAuthRoute) {
    if (isLoggedIn) {
      return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
    }
  }
  if (!isLoggedIn && !isPublicRoute) {
    return Response.redirect(new URL("/auth/login", nextUrl));
  }
  return true;
}
Russian BlueOP
I try with this? I am not sure if it is the currentUser() function, it is a wrapper to the auth() function
@Russian Blue I try with this? I am not sure if it is the currentUser() function, it is a wrapper to the auth() function
yes but from the error you just shown, we need to fix on auth.ts too
show the full code on auth.ts
Russian BlueOP
export const {
  handlers: { GET, POST },
  auth,
  signIn,
  signOut,
} = NextAuth({
  ...authConfig,
  providers: [
    Google({
      clientId:...
      clientSecret:..
    }),
    Credentials({
      async authorize(credentials) {
        const validatedFields = LoginSchema.safeParse();
        if (validatedFields.success) {
          const { email, password } 
          const user = await getUserByEmail(email);
const passwordsMatch = await bcrypt.compare(password, user.password);
        ],

  callbacks: {
    async signIn({ user, account }) {
      
      if (account?.provider !== "credentials") return true;

      if (!user || !user.id) return false;
      const existingUser = await getUserById(user.id);

      //prevent signin without email verification
      if (!existingUser?.emailVerified) return false;


    },
    async session(args) {
      const { session, token } = args as { session: Session; token: JWT };

      if (token.sub && session.user) {
        session.user.id = token.sub;
      }
      if (token.role && session.user) {
        session.user.role = token.role; //user.role
      }
      if (session.user) {
        session.user.name = token.name;
        session.user.email = token.email;
        session.user.isOAuth = token.isOAuth as boolean;
      }
      return session;
    },
    async jwt({ token, user }) {
    

      const existingUser = await getUserById(token.sub);
      if (!existingUser) return token;
      const existingAccount = await getAccountByUserId(existingUser.id);
      token.isOAuth = !!existingAccount;
      token.name = existingUser.name;
     
    },
    ...authConfig.callbacks,
  },
  events: {
 async linkAccount({ user }) {
      // automatically verify users logging in with google
      await db.user.update({
        where: { id: user.id },
        data: { emailVerified: new Date() },
      });
    },
  },

  adapter: PrismaAdapter(db), //prisma
  session: { strategy: "jwt" },
  // ...authConfig,
});
@Russian Blue export const { handlers: { GET, POST }, auth, signIn, signOut, } = NextAuth({ ...authConfig, providers: [ Google({ clientId:... clientSecret:.. }), Credentials({ async authorize(credentials) { const validatedFields = LoginSchema.safeParse(); if (validatedFields.success) { const { email, password } const user = await getUserByEmail(email); const passwordsMatch = await bcrypt.compare(password, user.password); ], callbacks: { async signIn({ user, account }) { if (account?.provider !== "credentials") return true; if (!user || !user.id) return false; const existingUser = await getUserById(user.id); //prevent signin without email verification if (!existingUser?.emailVerified) return false; }, async session(args) { const { session, token } = args as { session: Session; token: JWT }; if (token.sub && session.user) { session.user.id = token.sub; } if (token.role && session.user) { session.user.role = token.role; //user.role } if (session.user) { session.user.name = token.name; session.user.email = token.email; session.user.isOAuth = token.isOAuth as boolean; } return session; }, async jwt({ token, user }) { const existingUser = await getUserById(token.sub); if (!existingUser) return token; const existingAccount = await getAccountByUserId(existingUser.id); token.isOAuth = !!existingAccount; token.name = existingUser.name; }, ...authConfig.callbacks, }, events: { async linkAccount({ user }) { // automatically verify users logging in with google await db.user.update({ where: { id: user.id }, data: { emailVerified: new Date() }, }); }, }, adapter: PrismaAdapter(db), //prisma session: { strategy: "jwt" }, // ...authConfig, });
did you import authConfig?
Russian BlueOP
yeah like this import { authConfig } from "./auth.config";
i removed imports bcz msg too long here
@Russian Blue i removed imports bcz msg too long here
try restart the server
Russian BlueOP
yes reference error is gone
but app not working properly
if I go to login page, it says error too many redirects
Russian BlueOP
// array of routes accessible by a nyone and do not required authentication
export const publicRoutes = ["/", "/auth/new-verification"];

// These routes used for authentication and will redirect user to /tasks
export const authRoutes = [
  "/auth/login",
  "/auth/register",
  "/auth/error",
  "/auth/reset",
  "/auth/new-password",
];

// prefix for api authentication routes
// api authentication purposes
export const apiAuthPrefix = "/api/auth";
export const adminPrefix = "/admin";

export const DEFAULT_LOGIN_REDIRECT = "/tasks";
@Russian Blue // array of routes accessible by a nyone and do not required authentication export const publicRoutes = ["/", "/auth/new-verification"]; // These routes used for authentication and will redirect user to /tasks export const authRoutes = [ "/auth/login", "/auth/register", "/auth/error", "/auth/reset", "/auth/new-password", ]; // prefix for api authentication routes // api authentication purposes export const apiAuthPrefix = "/api/auth"; export const adminPrefix = "/admin"; export const DEFAULT_LOGIN_REDIRECT = "/tasks";
try this code
async function authorized({ auth, request: { nextUrl } }) {
  const isLoggedIn = !!auth?.user;

  const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix);
  const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
  if (isAdminRoute) {
    const user = auth?.user;
    return user?.role === UserRole.ADMIN;
  }

  if (!isPublicRoute) {
    if (isLoggedIn) return true;
    return false;
  } else if (isLoggedIn) {
    return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
  }

  return true;
}
Russian BlueOP
looks like its working now
do i try to build?
sure
Russian BlueOP
wohooo no error
thank you so much man, god bless you
Can I make the middleware even smaller or no need its fine?
@Russian Blue Can I make the middleware even smaller or no need its fine?
you could try to suggest it on next-auth github lol
Russian BlueOP
I have a weird error tho when I try to log in, something to do with trusted host
@Russian Blue Click to see attachment
are you running in production?
Russian BlueOP
yes
I think its fine if you deploy it with https
@Ray https://authjs.dev/reference/core#trusthost
Russian BlueOP
yeah I saw it but couldn't figure out how to set the option to true
@Ray I think its fine if you deploy it with https
Russian BlueOP
how can I test before I host tho :lolsob:
@Russian Blue how can I test before I host tho <:lolsob:753870958489632819>
 ...authConfig,
  trustHost: true,
  providers: [
Russian BlueOP
weirdly it doesn't work
@Russian Blue weirdly it doesn't work
do you have NEXTAUTH_URL env?
Russian BlueOP
just added it!
trying again now
@Ray do you have `NEXTAUTH_URL` env?
Russian BlueOP
http://localhost:3000/ correct? or without /
doesnt matter I think
http://localhost:3000 then
Russian BlueOP
do i have to restart build every time I change env?
Russian BlueOP
yeah
you will have to rebuild in production
Russian BlueOP
awesome man, I don't know how to thank you enough for pulling through
it's working
no prob