A JSON Web Token (JWT) is an open standard (RFC 7519) that securely sends and receives data between parties (in the form of a JSON object).
In this article, we’ll implement JWT authentication to secure a Node.js application. We’ll also find out what JWT is all about and build a demo app.
Let's get going!
What is a JSON Web Token (JWT)?
As defined in open standard RFC 7519:
A JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties.
A JWT is encrypted and signed with a secret key (using the HMAC algorithm) or a cryptographically protected set of keys (with RSA or ECDSA).
This authentication contributes to a web application's integrity by ensuring the integrity of the claims within it, known as tokens. When tokens are signed with public/private key pairs, the signature also confirms that only the person holding the private key signed it.
The tokens consist of three compact parts:
- Header: The header is divided into two sections: the type of token (JWT) and the signing algorithm used (HMAC-SHA256 or RSA).
- Payload: Assertions about an entity and supporting data, known as claims.
- Signature: Made up of an encoded header, an encoded payload, a secret, and an algorithm.
When to Use a JWT in Your Node.js App
Here are a couple of scenarios where JSON Web Tokens can be useful to your web application:
Authorization: The most common use of JWTs in most business applications.
JWTs enable businesses to protect or restrict access to a portion of an application for a select group of users. For each logged-in user, a JWT token is sent along with other subsequent requests. This allows a user to access routes, services, and resources permitted with that token.
Information Exchange: JSON Web Tokens are an excellent way to securely transmit data between parties.
Because JWTs can be signed (for example, with public/private key pairs), you can be confident that the senders are who they claim to be. Furthermore, because the signature is calculated using the header and payload, you can be certain that the content has not been tampered with.
Pre-requisites
Before you get started, ensure you have met the following requirements.
Create a New Project
Now let's create a project folder and a new Node.js project by running the commands below.
With the commands we:
- Create a new folder called jwt-auth
- Change the directory to the folder
- Create a
package.json
file to document the project dependencies
Now open the package.json
file and add the start script to run the application.
With the above configuration set up, run the command below.
Install Node.js App Dependencies
With the project created and configured, we'll now install the following dependencies:
Run the command below to install the required dependencies:
Set up an Express Server
Once the required dependencies are installed, create an index.js
file in the project folder, and set up an Express server with the code snippet below.
You have successfully created an Express server listening on port 3000, with middleware to parse the request payload.
Create A .env
File
A .env file is used in Node.js to store environment variables for security purposes. Ensure that your .env file is included in your .gitignore file to avoid exposing your application's secrets to the public.
Create a .env
file in the project's root directory and add your JWT secret.
Then go back to the index.js
file and configure the application to load the environment variables into your application, using dotenv
.
Build App Routes
With the environment variables set up, let's create a route to get all registered users in the application.
In index.js
, create a user array and route to return users with the code snippet below.
If you are integrating a database management system, you can run queries to find and return all the users instead. One thing to point out here is that this route is accessible to all users.
Create An Auth Route
Now let's create other routes to register and authenticate users in the application. We'll do that in the index.js
file, starting with the register route.
We import bcryptjs
to hash a user's password before saving it. Then we check if the user provides the required fields before adding them to the user's array.
Next, create another route to log in registered users.
Here, we import jsonwebtoken
to sign a token for the registered users.
First, we check if the users exist in the user's array. You can also run your find query if you are integrating a database.
Then we compare the password with the saved hashed version. When the user satisfies these checks, we then sign a token for the user passing the user's details, the JWT_SECRET, and expiration time.
Verify Your User's Token with Middleware
Now that we can register and authenticate a user in the application, let's create middleware to verify the user's token and thus protect our route.
Ensure this code snippet is above the app routes.
We send the token along with the request payloads in the request headers. We then check if the token was sent, and verify it using the jwt.verify
method.
Once a user is verified, we can save their details in the request object to keep track of their activities in the application.
Let's protect the get users route. Restrict access to only authorized users by adding the verifyUserToken
function as a middleware to the route.
Now, your application should look like this:
Test Your Node.js Application
Go ahead and test the application to see if it works as it should. Launch Postman and send a GET request to the endpoint localhost:3000/api/users
without authentication.
You should get an Unauthorized request
message.
Now, register an account by sending a POST request to the endpoint localhost:3000/api/register
, with the following JSON data in the request body.
Then, log in by sending a POST request to the endpoint localhost:3000/api/login
with the same data shown above.
JWT will generate a token for you, as shown here:
Finally, copy the auth token to the request headers and send a request to the get users endpoint again. The token should appear in the form's headers.
Now you have access to all users, until the token expires in one hour.
Wrapping Up
In this tutorial, you secured a Node.js application using JWT. We started by introducing you to JWT and touched on when you should use it, before building a demo app.
You can read more in the JWT documentation.
Happy coding!
P.S. If you liked this post, subscribe to our JavaScript Sorcery list for a monthly deep dive into more magical JavaScript tips and tricks.
P.P.S. If you need an APM for your Node.js app, go and check out the AppSignal APM for Node.js.