NodeJS is a very popular platform for building backend services and creating API endpoints. Several large companies use NodeJS in their microservices tech stack, which makes it a very useful platform to learn and know, similar to other popular languages like Java and Python. ExpressJS is a leading framework used for building APIs, and TypeScript provides necessary strict typing support, which is very valuable in large enterprise application development. TypeScript and ExpressJS combined together allow the development of robust distributed backend systems. Securing access to such a system is very critical.
The NodeJS platform offers several options for securing APIs, such as JWT (JSON Web Token), OAuth2, Session-based authentication, and more. JWT has seen a rise in adoption due to several key characteristics when it comes to securing the APIs. Some of the noteworthy benefits of using JWT to secure APIs are noted below:
In this tutorial, you will be building NodeJS-based microservices from scratch using Express and TypeScript in the beginning. The tutorial implements a library book management system where a user can view as well as edit a catalog of books. Later, you will be securing the endpoints of this microservice using JWT. The full code for the tutorial is available on this GitHub link. However, I encourage you to follow along for deeper insights and understanding.
To follow along in the tutorial, ensure the below prerequisites are met.
Create a new folder on your local machine and initiate a new NodeJS application using the commands below:
The next step is to initiate and define TypeScript configuration. Use the command below to create a new TypeScript configuration:
At this point, open the project folder in your editor and locate the freshly created file and update its content as per below:
Next, you should create a book controller. This controller will hold code for handling, receiving, and responding to actual API calls. Create directory under .
Add a file named under directory. Add the code below to this file. This controller code receives each individual API call, parses its request when needed, then interacts with the service layer (which you will build in the next steps), and responds to the user.
The controller interacts with the book service to perform reads and writes on the book database. Create a JSON file as per below with dummy books, which will act as the database.
Read this book's details in the service file and provide methods for updating the books as well. This code implements an in-memory book database. Add a directory under and add file with the code below.
Finally, start the application by using command . You should see output like below on the screen, and the server should start.
Similarly, you can use API endpoints to update or delete books as well. I have created a postman collection which you should be able to import use inside the postman. You can get at this link.
The API for creating new books is http://localhost:3000/api/books, and the API to delete the books is http://localhost:3000/api/books/:id.
At this point, you are ready to secure the APIs. You will need a list of users who can access the book management APIs. Create a dummy file under the data directory to hold our in-memory users.
Now it is time to create two file and which will hold login to provide a route to authenticate a user based on username and password.
Now, it's time to incorporate the authentication logic in each API call. Update the routes file to include the in each API call related to book management, as well as add a route related to login.
In the final step, initialize the memory user database. Update to make them look like the one below.
Calling APIs without providing the correct JWT token will now result in the below error from the server.
Before calling the APIs, you need to authenticate using the URL http://localhost:3000/api/login. Use this URL and provide your username and password. This will give you a valid JWT token, as illustrated below.
You should pass the received JWT to each API and preappend with the word bearer, as highlighted below. This will give you the correct response.
Securing your APIs is the most critical step in modern backend system design. So, congratulations on securing APIs with JWT. JWT makes authenticating APIs stateless and scalable. By leveraging JWT, your Node.js and Express APIs are now better equipped to handle real-world security challenges.