Using JWT in your Express app
As a backend engineer, you get a lot of control over how people are authenticated and their state is stored.
Back in the day, it was common to see "stateful" architecture, where all authentication data was stored in a database and the user got a state ID that connected the user to that specific entry in the DB.
Now, it was fine when the userbase was small, but as more users used your webapp, the overhead for querying the database got bigger.
In the image, the user performs an action that requires authorization (eg. post a blog). A sessionid is sent to the server (through cookies or headers) which is verified by the server by querying the database. If sessionid is valid, ie. it is present in the database, then the action is allowed to be performed.
This is simply too much work for something so trivial
Let me introduce you to a method of auth that doesn't need session data to be stored on the server, thus reducing overhead, improving user experience and speed.
Stateless auth using JSON Web Tokens
The basic idea of JWT is that instead of storing sessionids on the user, we store a JSON object in base64 format.
This is the typical flow for JWT based auth:
Do you see how much simpler it got? We eliminate the need to query our DB every time a user does something that needs auth. Fantastic!
(You can learn about JWT in depth here)
Implementing JWT in your Express App
Start by creating an npm package
$ npm init -y
Then install JWT, Expressjs and cookie-parser
$ npm install express jsonwebtoken cookie-parser
Then put the following into main.js:
'use strict'
const express = require("express");
const app = express();
const cp = require("cookie-parser");
const jwt = require("jsonwebtoken");
app.use(cp());
app.get("/login", (req, res)=>{
const token = jwt.sign({email: "[email protected]"}, "thiskeyisverysecret", {expiresIn: "7d"}); // Generate a jwt that will expire in 7 days
res.cookie("token", token, {httpOnly: true, maxAge: 60 * 60 * 24 * 7}); // Create an HttpOnly cookie that is valid for 7 days
res.send("You are now logged in!");
});
app.get("/protected", (req, res)=>{
try {
const user = jwt.verify(req.cookies["token"], "thiskeyisverysecret", {algorithms: ["HS256"]}); // Verify the cookie called "token" against secret key
res.send("Action performed!");
} catch(err) {
// An error is thrown if the JWT is invalid or has expired
res.send("You must be logged in to perform this action");
}
});
app.listen(8080);
console.log("Server started");
Let's understand what's going on here.
- We use cookie-parser for storing the JWT in cookie format in the user's browser.
- When the user
GET
s on/login
the server generates a JWT with the user's email and signs it with the secret key. This token is sent to the user as an HttpOnly cookie - When the logged in user
GET
s on a route that needs authorization, (here/protected
), then the JWT present in thetoken
cookie is verified against secret key. If the token is valid, the server allows the action.
Notes
- To simplify the tutorial, I have not included validation of user's credentials. Always check your user's credentials before granting a token!
- It is recommended to use short-life tokens for security; 7 days is too much
- Never store sensitive data (such as passwords) in JWTs. Any JWT can be easily deciphered to reveal the content. It is best to store uniquely identifying, but not sensitive information in JWTs (like usernames)
- Store as little data in JWTs as possible. Too much data increases the length of the JWT, causing bandwith issues.
Thanks for reading till the end. Here are some additional resources that may help you:
JSON Web Tokens Website
Advanced JWT use
Congratulations @rxge! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
You can view your badges on your Steem Board and compare to others on the Steem Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOP
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit