How to Use JWT in your Express App

in #security5 years ago

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.
What stateful architecture looks like

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:
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 GETs 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 GETs on a route that needs authorization, (here /protected), then the JWT present in the token 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

Sort:  

Congratulations @rxge! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You published your First Post
You got a First Vote
You made your First Vote
You made your First Comment

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:

The new SteemFest⁴ badge is ready
Vote for @Steemitboard as a witness to get one more award and increased upvotes!