How to use JSON web tokens with Node.js ?
JSON Web Token (JWT) is an Internet Standard that is used for exchanging data between two parties in a secure manner. It can’t be easily hacked as it creates a digital signature with the secret key along with the HMAC algorithm).
JWT Structure: JSON Web Tokens consist of three parts separated by dots (xxxxx.yyyyy.zzzzz), which are:
- Header: This contains the type of the token (JWT in this case) and the algorithm used.
- Payload: This contains the payload data that was used while creating the token
- Signature: The digital signature that is created using the header, payload, and secret key along with an algorithm as specified in the header).
Integration with Node.js:
Step 1: First up, initialize a simple node app using the below command and add express, dotenv package.
npm init -y npm i express dotenv
Step 2: Then, install JWT using the below command
npm i jsonwebtoken
Example: Let’s illustrate the use of JWT using a simple user authentication app.
Copy the below contents in the index.js file. For illustration purposes let’s assume we have a user “admin” with the password “admin”.
Our aim is to protect the “/home” endpoint using JWT that only authenticated users can access.
Javascript
const express = require( "express" ); const app = express(); app.use(express.json()); app.post( "/login" , (req, res) => { console.log( "Login router" ); res.json({ msg: "Login Endpoint" }); }); app.get( "/home" , (req, res) => { console.log( "Protected endpoint that only authorized users can access" ); res.json({ msg: "Home Endpoint" }); }); app.listen(8000, () => console.log( "Listening on 8000" )); |
First, we will use JWT to sign the token and send it back to the user on a successful login. Then on every subsequent request, the user will send the JWT token through the request header.
Create a .env file with the following content:
JWT_SECRET_KEY=<your_secret_key>
Replace with your secret key. This secret key is used by JWT to digitally sign the tokens. This shouldn’t be exposed in the codebase as it may lead to security breaches. This should be saved securely when working with real-time apps.
Now, let’s modify the login endpoint in the index.js file as below:
Javascript
// Add these two lines at the top of the file require( "dotenv" ).config(); const jwt = require( "jsonwebtoken" ); // Modify the login route as below app.post( "/login" , (req, res) => { const { username, password } = req.body; if (username === "admin" && password === "admin" ) { const token = jwt.sign({ username }, process.env.JWT_SECRET_KEY, { expiresIn: 86400 }); return res.json({ username, token, msg: "Login Success" }); } return res.json({ msg: "Invalid Credentials" }); }); |
Here when the user is successfully logged in, we are using JWT to sign the token with the username as the payload and it will expire in 86400 seconds (24 hours).
Steps to run the application: Now start the application using the below command:
node index.js
Open any REST Client of your choice (Postman/ Insomnia/ Thunder Client etc.,) and make a POST request to the login endpoint with the request body as below
When we run it, we will get a response as below:
Now copy the token and save it for later for the next request to the home endpoint. As the login endpoint is done, let’s move on to the home endpoint.
Now edit the index.js file as below:
Javascript
/* This middleware function is used to verify the token before granting access to the user to the protected endpoints. If the token is invalid it will restrict the user from accessing the protected endpoints We can use this middleware to any endpoints that we desire to make as protected*/ const verifyTokenMiddleware = (req, res, next) => { const { token } = req.body; if (!token) return res.status(403).json({ msg: "No token present" }); try { const decoded = jwt.verify(token, process.env.JWT_SECRET_KEY); req.user = decoded; } catch (err) { return res.status(401).json({ msg: "Invalid Token" }); } next(); }; // Modify the home endpoint as below // to use the verifyTokenMiddleware app.get( "/home" , verifyTokenMiddleware, (req, res) => { const { user } = req; res.json({ msg: `Welcome ${user.username}` }); }); |
Here, We have created a verifyToken middleware that verifies the validity and integrity of the token and the user will be able to access the home endpoint only if the token is valid.
Open the REST Client and try to access the home endpoint without any token.
When we run this we will get the below error.
Now, paste the token copied in the login step in the request header and try to access the home endpoint.
When we run this we will get the following success response.
Success!. When provided with the correct token, we are able to access the home endpoint. In this way, we can secure our Node.js apps using jwt.