JWT Made Easy!
Before jumping into JWT, let's see what HTTP means. HTTP is a stateless protocol used to transfer data over the web. Let's see what we mean by the word stateless here.
As you can see from the above diagram, even though the user had sent his credentials for the first time and received the response from the server, when he sends another request the server doesn't remember him. This is what we mean by the word stateless.
But when you visit any web app, for example, let's say you visit Facebook and visit one page(One request) and then visit another page(another request), how does it remember you or in technical terms how does it manage the Authorization?
Two of the popular ways of Authorization are:-
- Session tokens
- JSON web tokens
Let's understand Session tokens with an analogy:-
In diagram 1, the user goes to buy a book but the librarian asks him to fill a form and writes his details in the database and asks the user to remember the sessionId.
In diagram 2, the user goes to buy another book and hands over the sessionId which was given to him the last time. The librarian verifies the Id from the database and gives her the book.
Just like this authorization is done using a session token. Now let's see the drawback of this approach.
Since more and more systems nowadays are using the microservice architecture, if the sessionId is stored in one server, and the load balancer(basically a traffic cop which redirects the request to the preferable server) directs your request to another server that will not have that sessionId then this approach might not work. To solve this problem we will use the shared cache like Redis. But what if this shared cache only fails. This is a single point of failure.
Now let's look at the alternative which is JSON Web Token which will solve the above problem.
Compare this diagram with the earlier diagram where we were storing the session details in a database and having the user use the sessionId to maintain the session. In this approach, the librarian instead of storing the session details, hands over the signed library card to the user.
So when the user comes to the library again at the same branch or at any branch he just hands over the library card and he is good to go.
In this approach, the client needs to store the authorization details instead of the server and solves our problem. The library card here is the analogy of what we call Json Web Token. And to make the library card authentic the librarian signs it. Similarly, the server signs the token after creating and sends the signed token to the client.
Now lets see how you can use JWT in your Project.
exports.signin = (req,res)=>{const {email,password} = req.body;
const errors = validationResult(req)User.findOne({email},(err,user)=>{
if(err){
return res.status(400).json({
error: “User email does not exists”
})
}if(!user.authenticate(password)){
return res.status(401).json({
error: “Email and password does not match”
})
}//create token
const token = jwt.sign({_id:user._id},process.env.SECRET);//put token in cookie
res.cookie(“token”,token,{expire: new Date()+9999});//send response to front end
const {_id,name,email,role} = user;
return res.json({token,user:{_id,name,email,role}});})};
The above code is a SignIn method which I have used in my mern project. Important thing to note here is that after the user is validated, server creates a jwt token which is signed using userId in this case and a SECRET Key (you can set this to anything) and then puts that token in the cookie header of the request.
Now lets create a middleware (a function which can be executed between a request and a response) to check if the user is signedIn.
//protected routes
exports.isSignedIn = expressJwt({
secret: process.env.SECRET,
userProperty: “auth”,
algorithms: [‘HS256’]
})
expressJwt is an Express middleware for validating JWTs through the jsonwebtoken module. We pass our secret key, algorithm used and userProperty which we can set to anything and will contain our userId, i.e it will add a new property to the request with name “auth” and will contain the userId. It will look something like {auth: { “_id”:””}}. You can add many more configurations in JWT (refer https://www.npmjs.com/package/express-jwt).
Now use the middleware in your route. Thats it!
router.get(“/user/:userId”,isSignedIn,isAunthenticated, getUser);
Dont forget to add Authorization: `Bearer ${token}` in your headers while ajax call.
headers: {
Accept: “application/json”,
“Content-Type”: “application/json”,
Authorization: `Bearer ${token}`
},
You can get this token from your local storage as follows:-
if (localStorage.getItem(“jwt”)) {
return JSON.parse(localStorage.getItem(“jwt”));
}
Here is what a JWT token looks like :-
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vZXhhbXBsZS5vcmciLCJhdWQiOiJodHRwOi8vZXhhbXBsZS5jb20iLCJpYXQiOjEzNTY5OTk1MjQsIm5iZiI6MTM1NzAwMDAwMCwiZXhwIjoxNDA3MDE5NjI5LCJqdGkiOiJpZDEyMzQ1NiIsInR5cCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vcmVnaXN0ZXIiLCJjdXN0b20tcHJvcGVydHkiOiJmb28iLCJuYW1lIjoiUm9iIE1jTGFydHkiLCJpZCI6Nzh9.-3BnaA1XRiKh8e7zy9ZRTETf8VngoypqrVW98oQnH4w
I hope you enjoyed this article :) Happy Coding!