I'm trying to use JWT verification for authentication with middleware, but unfortunately, I'm getting some errors that cannot find a solution for.
./node_modules/jwa/index.js:3:0
Module not found: Can't resolve 'crypto'
Import trace for requested module:
./node_modules/jws/lib/sign-stream.js
./node_modules/jws/index.js
./node_modules/jsonwebtoken/verify.js
./middleware.ts
https://nextjs.org/docs/messages/module-not-found
You're using a Node.js module (crypto) which is not supported in the Edge Runtime.
Learn more: https://nextjs.org/docs/api-reference/edge-runtime
package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.9.3",
"@mui/material": "^5.8.6",
"@prisma/client": "^4.0.0",
"axios": "^0.27.2",
"buffer": "^6.0.3",
"cookie": "^0.5.0",
"jsonwebtoken": "^8.5.1",
"next": "12.2.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.33.0"
},
"devDependencies": {
"@types/node": "18.0.0",
"@types/react": "18.0.14",
"@types/react-dom": "18.0.5",
"eslint": "8.18.0",
"eslint-config-next": "12.2.0",
"prisma": "^4.0.0",
"typescript": "4.7.4"
}
}
middleware.ts
import { NextResponse } from "next/server";
import verify from "jsonwebtoken/verify";
import { urlToHttpOptions } from "url";
import type { NextRequest } from 'next/server'
const secret = process.env.SECRET;
export default function middleware(req: NextRequest) {
const { cookies } = req;
const { search, protocol, host } = req.nextUrl
const jwt = cookies.OutsiteJWT;
const url = req.url;
if (url.includes('/dashboard')) {
if (jwt === undefined) {
return NextResponse.redirect("http://localhost:3000/login");
}
try {
verify(jwt, secret); // <---- ERROR COMES FROM HERE
return NextResponse.next();
} catch (error) {
return NextResponse.redirect("/login");
}
}
return NextResponse.next();
}
/pages/api/auth/login.ts
/* eslint-disable import/no-anonymous-default-export */
import { sign } from "jsonwebtoken";
import { serialize } from "cookie";
const secret = process.env.SECRET;
export default async function (req, res) {
const { username, password } = req.body;
// Check in the database
// if a user with this username
// and password exists
if (username === "Admin" && password === "Admin") {
const token = sign(
{
exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30, // 30 days
username: username,
},
secret
);
const serialised = serialize("OursiteJWT", token, {
httpOnly: true,
secure: process.env.NODE_ENV !== "development",
sameSite: "strict",
maxAge: 60 * 60 * 24 * 30,
path: "/",
});
res.setHeader("Set-Cookie", serialised);
res.status(200).json({ message: "Success!" });
} else {
res.status(401).json({ message: "Invalid credentials!" });
}
}
I've tried commenting out the try/catch to check if the token is set, and it works correctly, but when I try to verify in the middleware it fails.
In version 12.2.0 the middleware is stable but also has some changes.
Does somebody else encounter similar issues or know how to solve this?