Bearer
in Authorization header is simply to tell the server that it's an API token, it has nothing to do with the permission for the user or which user is it.
To distinguish between user roles, you can put roles on your JWT payload. For example, if you decode this token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywicm9sZXMiOlsiQURNSU4iLCJOT1JNQUxfVVNFUiJdfQ.u0YXpuJkQ08RBb4_s6yVeGT3Ua21ptUbXvrzopG-txI
you will see that it has userId
and roles
in the payload, where userId
is the user id for that token, and roles
are the permission the user has.
So on your express app, you can do something like this:
try {
const payload = verifyToken(jwtToken);
} catch (err) {
// assuming if the verification failed because of invalid token will throw an error
return res.status(401).send(); // Unauthorized
}
// Check from roles array if it has "ADMIN" in it
if ( payload.roles.includes("ADMIN") ) {
adminOnlyFunction(); // Function that can be accessed by admin only
return res.status(200).send();
} else {
// If user has no ADMIN roles, return 403 instead
return res.status(403).send(); // Forbidden
}
But there is a drawback when using this method especially if the JWT token is long lived, let's say userId 1 have ADMIN permission, and before the token expired, you decided that userId 1 is no longer an admin, userId 1 will still be able to call adminOnlyFunction()
since the roles information is stored in the JWT payload. You can prevent this by blacklisting the token when you change the user's permission.
I personally wouldn't put roles
in the JWT payload, but instead store the user's roles information on your database, and check the roles every time an user sent a request to your server, you can read this answer on why you shouldn't put roles on your JWT, and the better way of doing it. At the end, it will always depends on your use case.