Reputation: 376
So I'm currently learning/building a REST API backend server for my web application using NodeJS, ExpressJS and JWT as the authentication. My query is regarding the best practice to identify the owner of the JWT token in the server without having to send a payload from the web application - as this limits the use of the GET HTTP method which I don't want to do.
You may ask why do I want to identify the owner of the JWT token, well all of the example tutorials from which I have learnt from have all taken the user to be the object required, which makes sense to simply have an endpoint saying GET /user/:userId. However for other user specific endpoints, such as a blog post, I really don't want to resort to GET /user/:userId/blog/:id and hence the pickle I'm in.
It is possible that I am overthinking this and that the simplest solution is staring me in my face - to which I apologise. But I have thought about a few ideas, including the one I am currently using, and I would like your feedback on it or if there is a better way of doing it.
Scenario: User is already logged in and they would like to view their blog at the endpoint GET /blog/:id but the server needs to validate that the user have access to view that blog
This is probably the simplest way to do it. I simply include the User ID inside the headers.
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${jwtToken}`,
UserId: userId
}
Is it good practice to enforce the need of sending additional data inside the header for all calls to the server, and more importantly is it safe to do so?
Another simple one so that it becomes GET /user/:userId/blog/:id. While this is fine, I just feel icky with the solution. But if this is considered the common practice, then so be it.
This is probably the "best" solution I can think of as it additionally serves as a another layer of authentication, and also easily identifies the owner of the token. However it adds another layer of complexity to the server which is fine if necessary, but I always feel that less is better.
Similar to the number 3, and is probably even easier than having to add a caching layer. However I don't know if there are any implications of using the DB as a temporary storage.
So that's where I'm currently at. I very much appreciate your time and response. Thank you in advance.
Upvotes: 1
Views: 815
Reputation: 13669
when user login , from backend you have to provide jwt token :
jwt.sign(payload,JWT_SECRET_KEY,{ expiresIn: JWT_EXPIRATION },(err, token) => {
res.json({
success: true,
token: 'Bearer ' + token
});
});
now from frontend side you have to save this token inside cookie
or localStorage
now when you have to access data which requires user id , for that you have to pass below headers in request :
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${jwtToken}`,
}
now you have to define route that requires user id like below :
router.get('/user', passport.authenticate('jwt', { session: false }),controllers.auth.user);
and you can simply get user information in req.user
code for controllers.auth.user :
module.exports=(req,res)=>{
res.json({
user:req.user
});
}
passport middleware will handle request that requires user is authenticated or not , if user is authenticated you can get user in
req.user
passport.authenticate('jwt', { session: false })
Upvotes: 0
Reputation: 29967
The user id is normally encoded in the JWT token and the JWT middleware then sets the attribute request.user
.
Upvotes: 1