'Role based permissions for api access in middleware NextJS
Is there a way to do role based permissions in middleware?
I'm asking this because I was hoping that there would be a way to call getSession in middleware.
Otherwise I would need to implement a helper function hasPermissions(req)
, import it and call it in every single file and I'm trying to avoid that
Thanks
Solution 1:[1]
if you do not want to use third party authenticatio server and you want to do on your own, you could write this with using cookeis and jwt.
1- when users logins set a jwt token. In next.js when user logins, make a request to api function and api function should handle the login process:
import jwt from "jsonwebtoken";
const handleLoginWithEmail = async (e) => {
e.preventDefault();
if (email) {
try {
//... add your logic, set state
// make a
const response = await fetch("/api/login", {
method: "POST",
headers: {
// pass this if you are using passwdrdless or other service that needs token
Authorization: `Bearer ${ifToken}`,
"Content-Type": "application/json",
},
});
} catch (error) {
console.error("Something went wrong logging in", error);
}
}
};
your api function should create a jwt
export default async function login(req, res) {
if (req.method === "POST") {
try {
// if there is
const auth = req.headers.authorization;
// add your logic
const token = jwt.sign(
{
...metadata,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000 + 7 * 24 * 60 * 60),
// I just create a custom object
"roles": {
"allowed-roles": ["user", "admin"],
"default-role": "user",
// you could decide the role based on email or userId. write your logic
"role":"user"
},
},
process.env.JWT_SECRET
);
// set the token
setTokenCookie(token, res);
res.send({ done: true });
} catch (error) {
console.error("Something went wrong logging in", error);
res.status(500).send({ done: false });
}
} else {
res.send({ done: false });
}
}
2- write a set cookie function used in above api function
import cookie from "cookie";
const MAX_AGE = 7 * 24 * 60 * 60;
export const setTokenCookie = (token, res) => {
const setCookie = cookie.serialize("token", token, {
maxAge: MAX_AGE,
expires: new Date(Date.now() + MAX_AGE * 1000),
secure: process.env.NODE_ENV === "production",
path: "/",
});
res.setHeader("Set-Cookie", setCookie);
};
3- write a verify token function
import jwt from "jsonwebtoken";
export async function verifyToken(token) {
if (token) {
const decodedToken = jwt.verify(token, process.env.JWT_SECRET);
console.log("decodedToken",decodedToken)
// get the token role from decodedToken
const userId = decodedToken?.issuer;
return {userId,role};
}
return null;
}
4- Finally in _middleware.js function:
export async function middleware(req, ev) {
console.log("ev in middleware", ev);
const token = req ? req.cookies?.token : null;
const {userId,role} = await verifyToken(token);
// got the role and add logic for role
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Yilmaz |