I'm building an applciation with Next.js that is purely for authenticating the users through JWT's, and then redirecting them to our main web application. Before the Next.js version 12 release I have used next-connect to run one middleware function on every api request to deserialize the user from the token or refreshing the access token if the refresh token is expired. I now wanted to move from next-connect to the new api middleware but first of all I'm not sure how these functions would perform in an self hosted environment, because with Vercel they would be deployed as edge functions but how do they work in a self hosted environment? Just as normal express middleware or not at all?
I also get the error eval not allowed in Middleware pages/api/_middleware because the standard jsonwebtoken package is not allowed in edge functions. This issue states that I would have to use the lightweight package @tsndr/cloudflare-worker-jwt, even though I'm not planing to use edge functions but rather deploy the app myself.
This is the middleware I'm trying to run through the _middleware file on every api request:
export async function middleware(req: NextApiRequestWithUser) {
const { access_token, refresh_token } = req.cookies;
if (!access_token) {
return NextResponse.next();
}
try {
// Verify token
const { payload, expired } = verifyAccessToken(access_token);
if (payload) {
if (!payload.userId) {
return new Response("User id is missing in JWT payload.", {
status: 401,
});
}
const currentUser = await User.findById(payload.userId).lean();
if (!currentUser) {
return new Response(
"The user belonging to this token no longer exist.",
{
status: 401,
}
);
}
req.user = currentUser;
}
const { payload: refreshPayload } = verifyRefreshToken(refresh_token);
if (!refreshPayload) return NextResponse.next();
const user = await User.findOne({ _id: refreshPayload.userId });
if (user?.refreshToken === refresh_token && expired) {
console.log("Refreshing access token");
const newAccessToken = generateAccessToken(refreshPayload.userId);
NextResponse.next().cookie(access_token, newAccessToken, {
domain: "localhost",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
path: "/",
});
return NextResponse.next();
}
return NextResponse.next();
} catch (error) {
console.log(error);
return NextResponse.next();
}
}