Learning about the concept of microservices in Nodejs, I have set up two microservices auth and users, both standalone and running on different ports.
The auth service handles user creation and log-in users using a username and password. This works as expected. I’ve used jwt to generate the tokens. I can easily create a user, create a session token and verify its validity.
My second service, users, I intend to use to show greetings to users and fetch a user’s detail. I need to use the auth service to know when a user is logged in in this setting.
However, with my current workings, when I try to go to an endpoint, /users/:id/sayhello
with a valid user id and a valid token passed in the headers, I get the following errors:
TypeError: Cannot read properties of undefined (reading 'id') at /path/auth/verifyToken.js:23:21
.
And then this; from jwt:
{
"name": "JsonWebTokenError",
"message": "secret or public key must be provided"
}
Let’s look at my setup now.
Here’s my verifyToken.js file from the auth service:
const verifyToken = (req, res, next)=>{
const authHeader = req.headers.token
// split the header, and get the token "Bearer token"
const token = authHeader.split(" ")[1];
if (authHeader) {
jwt.verify(token, process.env.JWT_SEC, (err, user)=>{
if (err) res.status(403).json(err);
req.user = user
next();
})
} else {
return res.status(401).json("You are not authenticated")
}
}
const verifyTokenAndAuthorization = (req, res, next) =>{
verifyToken(req, res, ()=>{
if(req.user.id === req.params.id){ // error traced back to this line
next();
}else{
res.status(403).json("Permission denied!");
}
})
}
From my users service, here’s the code that uses the auth service to know when the user is logged in then say hello.
app.get("/users/:id/sayhello", verifyTokenAndAuthorization, async (req, res) => {
try {
const user = await User.findById(req.params.id);
console.log(req.params.id) // undefined
res.status(200).json(`Hello ${user.username}`);
} catch (error) {
res.status(500).json(error);
}
});
I’ve with no success sought any leads from similar posts like A,B and C
I’m not sure of what’s not right. I’ll appreciate possible suggestions and leads towards a fix.
2
Answers
The authentication process got failed, so the user property was unset on the req object, so
req.user
isnull
.Ensure the integrity of your inputs.
I think in the
Headers
convention of usingAuthorization
orauthorization
key will not dissappoint as its the most preferred way of doing this have something likeI have done a rolebased approach in tackling this so check the implementation as of the question rolebased structure.
What to check for
Authorization
header is availabletoken
is present in theBearer token
AuthHeader
andtoken
are present then now you can be certain that you have the token, thus you can just return thejwt.verify(...args:[])
Athorization
then we override thenext
parameter with a function to execute on it`s behalfFrom here now you can check on the user Roles and return next based on what permissions they have.
Applying this to a middleware
Assuming you supply the middlewares to the given route its easy to abstract away the
verify jwt
and have alogin_required
based on the roles you want achieved.Full implementation of this I have on this Github repo Github link