JWS Authentication using Node.js and Express.js


Objectives

Learn how to use express.js to build a simple RESTful API to demonstrate JWS authentication.

Tech Stack

What is Middleware?

The middleware in node.js is a function that will have all the access for requesting an object, responding to an object, and moving to the next middleware function in the application request-response cycle. This function can be used for modifying the req and res objects for tasks like adding response headers, parsing requesting bodies, and so on. Checkout this post to learn more information about middleware.

JWT Implementation: Access Token

Overview

This app is a Node.js application using Express.js that serves a list of posts. It includes authentication using JSON Web Tokens (JWT) to protect the "/posts" endpoint, ensuring that only authorized users can access posts that belong to them.

Create our server

  • app.use(express.json()): Adds a middleware to the Express application that parses incoming JSON data. It allows the application to handle JSON payloads in requests.
  • app.get("/posts", authenticateToken, (req, res) => {...}): Sets up an HTTP GET route at the path "/posts". When a client sends a GET request to "/posts", the authenticateToken middleware function is executed first, and then the callback function for the route is called if the authentication is successful.
  • function authenticateToken(req, res, next) {...}: This is a middleware function named authenticateToken. Middleware functions have access to the request (req) and response (res) objects and can perform actions before passing control to the next middleware or route handler.

Create another authentication server

In this code snippet, when a client sends a POST request to "/login" with a username in the request body, the server authenticates the user (in this case, just creating a user object with the username). The server then generates an access token using the generateAccessToken function, which includes the user information (username) and an expiration time of 60 seconds.

Here we can utilize a vscode extension REST Client to test our server.

Send a POST request to the server

POST http://localhost:4000/login
Content-Type: application/json

{
    "username": "Willie"
}
          

You will receive a response from the server similar to this:

Substitute the access token in your GET request, and then you can proceed to request the server again.

GET http://localhost:3000/posts
Authorization: Bearer {YOUR_ACCESS_TOKEN}

You will receive a response (all the posts belongs to a specific user, in this case: Willie) from the server similar to this:

JWT Implementation: Refresh Token

Here we modify authServer.js, and implement the /token endpoint to exchange a refresh token for a new access token. Notice that we are using an array to store the refresh tokens, which is not a good practice in production. In production, you should store the refresh tokens in a database.

Now that we can obtain access tokens based on the refresh token, there is a concern that users could have infinite access to our API, which is not desirable. To address this issue, we must implement a deauthentication mechanism to revoke the refresh token when necessary.

Deauthentication (Logout)

In the code snippet below, we add a logout endpoint that deletes the refresh token from the array of refresh tokens. In production, you should delete the refresh token from the database.

Let's test out our /logout endpoint:

DELETE http://localhost:4000/logout
Content-Type: application/json

{
    "token": {YOUR_REFRESH_TOKEN}
}

When the user send a POST request to this endpoint, the user no longer has the access to our backend anymore!

Conclusion

That's a wrap! With Express.js, we can conveniently test JWS Authentication and simulate how it works. Hope you enjoy this post!

Source