Securing Express.js API Using JWT
By: Bewar Salah
Tags: Jwt, Authentication, Programming, Expressjs, JavaScript

Express.js — JWT Authentication

In this post, I will show you how to integrate JWT authentication into Express.js applications using jsonwebtoken.

Introduction

We need to secure user’s data from being changed or displayed without permission. There are many types of authentications. We usually secure web APIs using JWT authentication. This method suits best for web APIs. It does not require to store cookies on client or sessions on the server. It is a stateless way of authorizing resources. It is super easy to implement. It is very popular method for authenticating web APIs among the others.

There are many articles written about this topic. I will try to minimize the topic and show the best practices with some security concerns like hashing passwords. Jsonwebtoken is an NPM package that can generate JWT tokens and verify them. We also use bcrypt package to hash the passwords before saving it in DB. It protects the password from being displayed by DB administrators.

What is JWT?

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties — https://jwt.io

In real world applications, there will be many web APIs to read or write a resource. We need to authorize some people to do certain actions. If an unauthorized person tries to make an authorized action should receive a 401 http status code in the response.

Let us demonstrate this with an example. First, let us consider we have a resource Users. The bellow display the steps for JWT authentication demonstration;

First we try to fetch users and display without any authentication. The API returns unauthorized with status code 401 .

. Then we try to login and receive a JWT token generated by the application

Finally, the token can be used to validate the authorized API and display the users.

Diagram/ demonstrating JWT authentication

Authorizing API

There are many ways to authorize application resources. An easy way is to create a middleware and inject any express.js route that needs to be authorized.

Let us consider our example, the resource GET /USERS. We are required to retrieve a list of users stored in DB and only authorized users should be able to retrieve it.

The middleware checks the authorization in the header of the request that contains a JWT token.

It verifies the token using jsonwebtoken library.

const authenticateMiddleware = (req, res, next) => {

const { authorization } = req.headers;

const token = authorization && authorization.split(" ")[1];

if (token == null) return res.sendStatus(401);

jwt.verify(token, SECRET_KEY, (err, user) => {

if (err) return res.sendStatus(403);

req.user = user;

next();

});

};

This middleware can be injected in any route of Express.js application.

app.get("/api/users", authenticateMiddleware, async (req, res) => {

const { id } = req.params;

const { title, content } = req.body;

var blog = await User.find({});

res.json({

success: true,

blog,

});

});

Now if we try fetch the API without token or event with an invalid token we receive unauthorized 401.

Fetching an Authorized Resource

Generate JWT Token

So, before trying to read or write any authorized resources, we need to have a JWT token.

The easiest way to generate a JWT token, is to allow the user to send username/password to the server. The server validates the username/password against the users stored in DB. Finally, if the user exists in DB, the app generates and sends a token to the client.

It is a good idea to hash the password before saving. This restricts authorized DB users from login using the hash only. bcrypt.js is an NPM package that enables our application to hash password and compare the plain password with the hashed one.

app.post("/api/user/login", async (req, res) => {

const { username, password } = req.body;

const user = await User.findOne({ username });

if (user == null) {

res.sendStatus(401);

return;

}

bcrypt.compare(password, user.hash, (err, result) => {

if (err) res.sendStatus(401);

else if (!result) res.sendStatus(401);

else {

jwt.sign({ id: user._id }, SECRET_KEY, (err, token) => {

if (err) res.sendStatus(500);

else res.json({

success: true,

user: { username: user.username },

token,

});

});

}

});

});

Login

Validating Requests

Now, we need to select Bearer Token in authorization tab. The users are retrieved and displayed in the body of the request.

Reading an Authorized Resource

Complete Example

The bellow is the complete example of authorizing an express.js application using JWT. In this example, I have created two resources Users and Blogs.

POST: API/Users/Login — Only this route is not authorized. It is used by users to login and generate JWT token.

Only this route is not authorized. It is used by users to login and generate JWT token. The other routes are authorized and require authorization in the header.

Conclusion

This was a complete guide on how to use jsonwebtoken library to secure Express.js applications. If you are not familiar with Express.js applications, previously I have created a tutorial on Creating APIs using Express.js.