Basically, I am trying to create middleware in my next js project, I have a fully functional login system using next auth, and now I want to redirect users to different dashboard pages based on their role after logging in. For example, if the user role is admin then the user should be redirected to the /admin page and if the user role is donor then the user should be redirected to the /donor page and I want to do it using middleware.js,
However, I am unable to get the session to extract the user role present in the session. It returns a null value. but I can get the session in normal react components like the one below
const {data: session} = useSession()
const role = session?.user?.role
But I am unable to get the session using getSession() in the middleware.js
Note: useSession() does not work for middleware
export { default } from "next-auth/middleware";
import { NextResponse } from "next/server";
import { getSession } from "next-auth/react";
export const config = {
matcher: ["/admin/:path*", "/donor/:path*"],
};
// Define the paths for different roles
const roleRedirects = {
admin: "/admin",
donor: "/donor",
};
export async function middleware(request) {
const session = await getSession({request});
const role = session?.user?.role;
console.log(session); // getting null value
if (session && role && roleRedirects[role]) {
return NextResponse.redirect(roleRedirects[role]);
}
return NextResponse.next();
}
for better understanding I have added my [...nextauth].js code also
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcryptjs";
import { connectDB } from "@/backend/utils/dbConnect";
import prisma from "@/prisma/prismaClient";
export const handler = NextAuth({
providers: [
CredentialsProvider({
name: "credentials",
credentials: {},
async authorize(credentials, req) {
const { identifier, password } = credentials;
try {
await connectDB();
const user = await prisma.users.findFirst({
where: {
OR: [{ email: identifier }, { phone: identifier }],
},
});
if (user !== null) {
const passwordMatching = await bcrypt.compare(
password,
user.password
);
if (passwordMatching !== false) {
return user;
} else {
return null;
}
} else {
return null;
}
} catch (error) {
return {
apiMessage: {
errorMsg: "Unexpected Error occurred ",
error: error,
},
};
}
},
}),
],
// session
session: {
strategy: "jwt",
maxAge: 7 * 24 * 60 * 60, // Set the session max age 7 days
expires: 30 * 24 * 60 * 60, // set the session expiration time 30 days
},
callbacks: {
async jwt({ token, user }) {
user && (token.user = user);
return token;
},
async session({ session, token }) {
session.user.id = token.user.id;
session.user.role = token.user.role;
delete session?.user?.email;
delete session?.user?.phone;
delete session?.user?.password;
return session;
},
},
pages: {
signIn: "/login",
},
secret: process.env.NEXTAUTH_SECRET,
});
export { handler as GET, handler as POST };
I have resolved it, I have used getToken() in the middleware to get the session Here is the middleware.js file of NextJs
import { NextResponse } from "next/server";
import { getToken } from "next-auth/jwt";
// Protected routes for each role
const respectiveRoutes = {
admin: "/admin",
donor: "/donor",
};
// specify pages for middleware
export const config = {
matcher: ["/admin/:path*", "/donor/:path*", "/login", "/signup"],
};
export async function middleware(request) {
const { nextUrl } = request;
// Get session and extract user role
const session = await getToken({
req: request,
secret: process.env.NEXTAUTH_SECRET,
});
const userRole = session?.user?.role.toLowerCase(); // get the user role from session
// Redirect logged in user's to their respective dashboard
if (session) {
const rolePath = respectiveRoutes[userRole];
if (nextUrl.pathname.startsWith(rolePath)) {
return NextResponse.next();
} else {
// if users try to visit anauthorised dashboard, they will be redirected to their own dashboard
for (const role in respectiveRoutes) {
if (role !== userRole && nextUrl.pathname.startsWith(respectiveRoutes[role])) {
//
return NextResponse.redirect(`${process.env.NEXTAUTH_URL}${rolePath}`);
}
}
}
// prevent loggedin user to visit login and signup page
if (nextUrl.pathname == "/login" || nextUrl.pathname == "/signup") {
return NextResponse.redirect(`${process.env.NEXTAUTH_URL}${rolePath}`);
}
} else {
// Redirect logged out users to login page is they want to visit protected routes
if (["/admin", "/donor"].some((rolePath) => nextUrl.pathname.startsWith(rolePath))) {
return NextResponse.redirect(`${process.env.NEXTAUTH_URL}/login`);
}
}
// Allow other requests to proceed
return NextResponse.next();
}