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.
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
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.
There might be two ways you can fix this:
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");
},
}),
],
});
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