I was using nextAuth with Pages router and i want to switch to Api router but i ‘m getting some error. I have created a testing project to make everything work before i change that in my real project. So in the test project, i have 2 pages: the homePage and the adminPage. In the homePage i have a login form and i’m using the credentials providers to connect, if it’s connected successfully, i want to be redirected to adminPage. I’m using mongodb atlas, [email protected] and [email protected].
I don’t have a problem with the db connection. The problem comes from the initialization of the […nextauth]/route.js file. I have used 2 method, the first Method is :
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import User from "@/app/user";
const handler = NextAuth({
session: {
strategy: "jwt",
},
providers: [
CredentialsProvider({
async authorize(credentials, req) {
dbConnect();
const { email, password } = credentials;
console.log("We are here");
const user = await User.findOne({ email }).select("+password");
console.log("user from db");
console.log(user);
if (!user) {
console.log("No user found");
return "Invalid Email or Password";
}
console.log("User found");
const isPasswordMatched = password === user?.password;
if (!isPasswordMatched) {
console.log("Password don't match");
return "Invalid Email or Password";
}
console.log("Password match");
return user;
},
}),
],
callbacks: {
jwt: async ({ token, user }) => {
user && (token.user = user);
if (req.url === "/api/auth/session?update") {
// hit the db and return the updated user
const updatedUser = await User.findById(token.user._id);
token.user = updatedUser;
}
return token;
},
session: async ({ session, token }) => {
session.user = token.user;
// delete password from session
delete session?.user?.password;
return session;
},
},
pages: {
signIn: "/",
},
secret: process.env.NEXTAUTH_SECRET,
});
export { handler as GET, handler as POST };
So None of the console.log shown in this code is diplayed and it only says error with a status code 401. My login email and password are correct.
error shown in the terminal: “POST /api/auth/callback/credentials 401”
The second method is :
export default async function auth(req, res) {
// Do whatever you want here, before the request is passed down to `NextAuth`
return await NextAuth(req, res, {
session: {
strategy: "jwt",
},
providers: [
CredentialsProvider({
async authorize(credentials, req) {
dbConnect();
const { email, password } = credentials;
const user = await User.findOne({ email }).select("+password");
if (!user) {
return "Invalid Email or Password";
}
const isPasswordMatched = password === user?.password
if (!isPasswordMatched) {
return "Invalid Email or Password";
}
return user;
},
}),
],
callbacks: {
jwt: async ({ token, user }) => {
user && (token.user = user);
if (req.url === "/api/auth/session?update") {
// hit the db and return the updated user
const updatedUser = await User.findById(token.user._id);
token.user = updatedUser;
}
return token;
},
session: async ({ session, token }) => {
session.user = token.user;
// delete password from session
delete session?.user?.password;
return session;
},
},
pages: {
signIn: "/",
},
secret: process.env.NEXTAUTH_SECRET,
});
}
The error of this method is “Not exporting HTTP Method”, not any other clarifications. I have checked the document of nextAuth and i didn’t find anything that could help me.
Here is a screen caption of the terminal:
I want to use the second method for my project but i wouldn’t mind if you can help correct both of the 2 ways
Here is the middleware.js :
import { withAuth } from "next-auth/middleware";
import { NextResponse } from "next/server";
export default withAuth(
async function middleware(req) {
const url = req.nextUrl.pathname;
const userRole = req?.nextauth?.token?.user?.role;
if (url.startsWith("/api")) {
NextResponse.next().headers.append("Access-Control-Allow-
Origin", "*");
}
if (url?.startsWith("/admin") && userRole !== "admin") {
return NextResponse.redirect(new URL("/", req.url));
}
},
{
callbacks: {
authorized: ({ token }) => {
if (!token) {
return false;
}
},
},
}
);
export const config = {
matcher: ["/admin/:path*"],
};
Here the model of user :
import mongoose from "mongoose";
import bcrypt from "bcryptjs";
const userSchema = new mongoose.Schema({
name: {
type: String,
required: [true, "Please enter your name"],
},
phone: {
type: String,
required: [true, "Please enter your mobile number"],
},
email: {
type: String,
required: [true, "Please enter your email"],
unique: true,
},
password: {
type: String,
required: [true, "Please enter your password"],
minLength: [6, "Your password must be longer than 6
characters"],
select: false,
},
avatar: {
public_id: String,
url: String,
},
role: {
type: String,
default: "user",
},
createdAt: {
type: Date,
default: Date.now,
},
});
userSchema.pre("save", async function (next) {
if (!this.isModified("password")) {
next();
}
this.password = await bcrypt.hash(this.password, 10);
});
export default mongoose.models.User || mongoose.model("User",
userSchema);
2