Sample JWT Authentication in Node.js

Sample JWT Authentication in Node.js

JWTs are compact, simple and great for data transfer, authentication and authorisation. To get a basic knowledge of JWTs, go read my article here. Today, we would create a simple authentication app. For this sample, we would need a code editor (here, I used Visual Studio Code) and Postman. The sample code is also available here.

You can download Visual Studio Code on their website and get Postman here.

Setting up

Open VS code or the editor of your choice, create and open a new directory named JwtAuth. Then, with a Terminal, run npm init and provide the information needed. Next, run npm i express jsonwebtoken body-parser to install the packages we would be using. Add a new file to the directory and name it index.js.

jwtauth1.jpg

First steps

Over to the code. Open index.js and import the modules.

const express = require("express");
const parser = require("body-parser");
const jwt = require("jsonwebtoken");

Next, we are going to hardcode a username and password which we would use for the authentication. To get a token, the input username and password must match these values.

const username = "hallixon";
const password = "@Password1";

Create a secret and a payload that would be used for the JWT sent after the user authenticates.

const payload = {
    sub: 1234567890,
    name: "Emmanuel Allison",
    role: "admin",
    age: 31,
};
const secret = "Shhhh! This is a secret";

Alright, it's time to set up the express app and its middleware.

var app = express();
app.use(parser.json()); // This parses the body of HTTP requests to a JSON object.

Endpoints

Great, you’ve made it this far. Now, we have to set up the endpoints. We would have two endpoints: /auth for authentication and /verify for verification. Let’s first work on the one for authentication. It would receive the username and password in the body of the request, and check if they match the defined username and password. If they do, then it signs the token and sends it to the user.

app.post("/auth", (req, res) => {
    if (req.body.username == username && req.body.password == password) {
        // Sign the JWT.
        const signed = jwt.sign(payload, secret, {
            algorithm: "HS256",
            expiresIn: "60s"    // The token won't expire if this is left out.
        });
        return res.send(signed);
    }
    res.status(401).send("Not authenticated.");
});

Next up is the verification which would receive a token in the request’s body and verify it. If the token is expired or is not valid, it sends a 401 HTTP status with the message, “Invalid or expired token.”

Note, however, that in production, the token should be sent in the Authorization header of the request as a Bearer token.

app.post("/verify", (req, res) => {
    jwt.verify(req.body.jwt, secret, {
        // Always indicate the algorithm to avoid alg stripping attacks.
        algorithms: ["HS256"]
    }, (error, decoded) => {
        if (error) return res.status(401).send("Invalid or expired token.");
        res.send(
            `Hi ${decoded.name}, you are an ${decoded.role}, and you are ${decoded.age} years old.`
        );
    })
})

And finally, we set the app to listen on port 3000.

app.listen(3000);

Testing the endpoints

In your Terminal, run node index.js to start the server. Open Postman. Select the POST method and enter the URL http://localhost:3000/auth. Send the request. You should receive an error because we didn't pass in the username and password.

jwtauth2.jpg

Now let’s pass in the username and password. In Postman, click on Body, select raw and from the drop-down menu, choose JSON. Put this in:

{
    "username": "hallixon",
    "password": "@Password1"
}

Send the request and you should get a token.

jwtauth3.jpg

Awesome! Let’s verify the token. Open a new tab in Postman. Select the POST method and set the URL to http://localhost:3000/verify. Just like in the last, click on Body, select raw and choose JSON from the menu. The object sent should look like this:

{
    "jwt": "<your token here>"
}

Send the request, and if it sends an error, then the token is either invalid or has expired (remember, we set the tokens to expire after 60 seconds).

jwtauth4.jpg