reactjsmongodbauthenticationnext.jsnext-auth

The edge runtime does not support Node.js 'crypto' module error while adding mongoClient in Auth Js (Next js)


I have implemented auth js in the next js project. I also split the config like, auth.js and auth.config.js.

Now for the signIn functionality, if I add mongoClient to my auth.config.js, I am getting an edge runtime error.

How can I solve this???

Below is my code:

//auth.config.js

import { NextAuthConfig } from "next-auth";
import Credentials from "next-auth/providers/credentials";
// import { getUserFromDB } from "./lib/db-utils";

const authConfig = {
  providers: [
    Credentials({
      credentials: {
        email: {},
        password: {},
      },

      authorize: async (credentials) => {
        let user = null;

        // user = await getUserFromDB(credentials.email);

        if (user) {
          const isPasswordValid = bcrypt.compareSync(
            credentials.password,
            user.password
          );

          if (isPasswordValid) {
            return { name: user.name, email: user.email };
          }
        }

        // If user is not found or password is invalid, return null
        throw new Error("Invalid credentials");
      },
    }),
  ],
};

export default authConfig;

//auth.js

import NextAuth from "next-auth";
import authConfig from "./auth.config";
import { MongoDBAdapter } from "@auth/mongodb-adapter";
import clientPromise from "./lib/db";

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: MongoDBAdapter(clientPromise),
  session: { strategy: "jwt" },
  ...authConfig,
});


//db.js

import { MongoClient, ServerApiVersion } from "mongodb"
 
if (!process.env.MONGODB_URI) {
  throw new Error('Invalid/Missing environment variable: "MONGODB_URI"')
}
 
const uri = process.env.MONGODB_URI
const options = {
  serverApi: {
    version: ServerApiVersion.v1,
    strict: true,
    deprecationErrors: true,
  },
}
 
let client
let clientPromise
 
if (process.env.NODE_ENV === "development") {
  // In development mode, use a global variable so that the value
  // is preserved across module reloads caused by HMR (Hot Module Replacement).
  let globalWithMongo = global 
 
  if (!globalWithMongo._mongoClientPromise) {
    client = new MongoClient(uri, options)
    globalWithMongo._mongoClientPromise = client.connect()
  }
  clientPromise = globalWithMongo._mongoClientPromise
} else {
  // In production mode, it's best to not use a global variable.
  client = new MongoClient(uri, options)
  clientPromise = client.connect()
}
 
// Export a module-scoped MongoClient promise. By doing this in a
// separate module, the client can be shared across functions.
export default clientPromise

Help me please.

I want to have a solution for this. I tried exactly as the official doc said, but I don't know how to implement the login logic for credentials.


Solution

  • Recently, I encountered an error similar to the one you described. After conducting thorough research, I discovered two key factors contributing to the issue: the @auth/mongodb-adapter and the bcrypt package. Both of these dependencies rely on the crypto module, which becomes problematic when importing auth into middleware that operates within the Edge runtime.

    I followed the solution from the following resources

    https://authjs.dev/guides/edge-compatibility

    https://nextjs.org/learn/dashboard-app/adding-authentication

    Here is how I fixed it:

    Middleware Adjustment

    To fix the problem, I pasted the code in the middleware.js file from the official doc linked above.

    // ./middleware.js
    
    import authConfig from "./auth.config";
    import NextAuth from "next-auth";
    
    export const { auth: middleware } = NextAuth(authConfig);
    

    MongoDBAdapter related problem should be fixed upon doing this. But the same error will show again because of bcrypt package. Because you are using bcrypt package inside auth.config.js which will be imported in middleware.js file.

    Fixing bcrypt problem

    There might be two ways you can fix this:

    1. Using bcrypt package in auth.js file: As this nextjs guide suggests https://nextjs.org/learn/dashboard-app/adding-authentication#protecting-your-routes-with-nextjs-middleware, instead of using using CedentialProvider in auth.config.js file, You can leave providers array empty in this file like this:

      // ./auth.config.js
      
      export const authConfig = {
        pages: {
          signIn: "/login",
        },
        providers: [], // Add providers with an empty array for now
      };
      

      And then implementing providers in the auth.js file like this. So you can use bcrypt package in this file. No need to install brypt-egde package.

      // auth.js
      
      import NextAuth from "next-auth";
      import Credentials from "next-auth/providers/credentials";
      import { authConfig } from "./auth.config";
      import bcrypt from "bcrypt";
      // import { getUserFromDB } from "./lib/db-utils";
      
      export const { auth, signIn, signOut } = NextAuth({
        ...authConfig,
        providers: [
          Credentials({
            credentials: {
              email: {},
              password: {},
            },
            authorize: async (credentials) => {
              let user = null;
      
              // user = await getUserFromDB(credentials.email);
      
              if (user) {
                const isPasswordValid = bcrypt.compareSync(
                  credentials.password,
                  user.password
                );
      
                if (isPasswordValid) {
                  return { email: user.email };
                }
              }
      
              // If the user is not found or the password is invalid, return null
              throw new Error("Invalid credentials");
            },
          }),
        ],
      });
      
    2. Using bcrypt-edge package: You can install bcrypt-edge package via:

      npm i bcrypt-edge

      Then you can use this package inside the auth.config.js file.

      Package link: https://www.npmjs.com/package/bcrypt-edge