The Complete Guide to JSON Web Tokens

The Complete Guide to JSON Web Tokens

In this article, we will take a look at what JSON Web Token is all about and hands-on guide to JSON Web Token Authentications

In this article, we will take a look at what JSON Web Token is all about and hands-on guide to JSON Web Token Authentications

JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties.

We will start with a basic explanation of JWT, then look at its structure, and finally create a simple server that will take some data and insert it into a JWT.

What is a JSON Web Token and why do we need it?

A *JSON Web Token (JWT) *is a safe, compact, and self-contained way of transmitting information between multiple parties in the form of a JSON object.

Say you want to log in to an app, like say Tinder. Tinder allows users to log in using their Facebook profile. So when the user selects the option to log in using Facebook, the app contacts Facebook’s Authentication server with the user’s credentials (username and password).

Once the Authentication server verifies the user’s credentials, it will create a JWT *and sends it to the user. The app now gets this *JWT and allows the user access to its data.

JWT’s Structure

A JSON Web Token consists of three parts that are separated by a “.”. They are:

  • Header
  • Payload
  • Signature

The header typically consists of two parts: the token’s type, and the hashing algorithm that is being used.

{
  "alg": "HS256",
  "typ": "JWT"
}

The payload is where the actual information that we want to send is stored. Here is an example of a simple payload. Know that payloads can be way more complicated than this to ensure better security.

{
  "sub": "65165751325",
  "name": "Rajat S",
  "admin": true
}

The signature is used to verify that the message was not altered before reaching its destination. This is usually done by using private keys.

These three parts are usually encoded into three Base64-URI strings that are separated by a . in between them.

To easily decode, verify, generate, or just play around with JWTs, check out the JWT.IO Debugger by Auth0.

Now that we have a basic understanding of what a JSON is, lets take a look at how to build a simple authentication server that will issue JWT, which we will then use to access an API.

Getting Started

To get started, lets build a simple web server. First, install the express library onto your system using NPM. Simply open a command terminal and run the command:

$ npm install express

Next, create a new folder named jwt-auth. You can name it something else if you want.

$ mkdir jwt-auth
$ cd jwt-auth

Inside this folder create a new file called index.js. This where we will write our code to set up a web server that will have a single route that displays the current date and time and a handler for 404 pages.

Open a code editor (I ❤ VS Code) write the following code inside it:

const express = require("express");
const app = express();
const PORT = 8888;
app.get('/time', (req, res) => {
  const time = (new Date()).toLocaleTimeString();
  res.status(200).send(`The Time is ${time}`);
});

Here, we are first importing the express library that we had just installed. Then I am creating a new const called app that will use the express library. I am also creating another const called PORT which will contain the port number on which our server will run. I have selected 8888 as the port number. You can use any other port number if you want as well.

Next, I have created a new route called time. This route takes a callback with response and request as parameters. In short, this route will display the current local time to the user.

Let’s also add a route for the case when tell the server to takes us anywhere but to time. This is called a *catchall route. *I want the server to return a 404 error on this route. To implement this, write the following code into our index.js file:

app.get("*", (req, res) => {
  res.sendStatus(404);
});

One last thing left to do. We have not told our server on which port to listen. We have initialized the PORT number as 8888. But we have yet to actually use this const in our code. To do this, use the app.listen method as shown below:

app.listen(PORT, () => {     
  console.log(`Server is running on port ${PORT}.`); 
});

With that done, we can start the server by typing node . in our command terminal. Then, go to localhost:8888 and you will find that it displays a Not Found message. Add /time to the URL and it will not display the local time as shown below:

In short, we have built an express server that will show us the local time at /time and a 404 error on any other route.

Implementing a Login Route

Since this article is about JWT Authentication, let’s implement a route called login. Unlike the routes in the previous sections, which used get and listen, this route will be created using post.

app.post("/login", (req, res) => {
  const user = req.body.username;
  res.status(200).send(`User's name is ${user}`);
})

But currently our server cannot read the body of the requests. To solve this, we will install a new middleware library called body-parser.

$ npm install body-parser

Then just like we did with the express library, import it into the index.js file using the require syntax.

const bodyParser = require("body-parser");

We can now tell express to use body-parser to handle all the JSON responses as shown below:

app.use(bodyParser.json());

Now start the server by running the node . command.

In order, to test this new route, we will need to use POSTMAN. Install this into your system, if you don’t already have it.

Inside POSTMAN, create a post request to the login route as shown below:

Inside the body, create a JSON Object as shown below:

Clicking on send should get you the following response:

Issuing JWTs

Now that we have built a simple server that can handle GET, and POST requests, let’s build a simple JWT issuer.

Lets start by creating a new array called users that will contain a couple of users along with their passwords as shown below:

const users = [
  {id: 1, username: "clarkKent", password: "superman"},
  {id: 2, username: "bruceWayne", password: "batman"}
];

Lets rewrite the /login route. Here, we will first check if the submitted request contains both a username and password. If that is not the case, then the server should respond with a 400 status.

app.post("/login", (req, res) => {
  if (!req.body.username || !req.body.password) {
    res.status(400).send("Error. Please enter the correct username and password");
    return;
  }

Next, if the request valid, we will need to check if the user in the request is present in our users array. In the same /login route below the if statement, write:

const user = users.find((u) => {
  return u.username === req.body.username && u.password === req.body.password;
});

But if the user in the request is not present in the users array, we need to respond with a status code of 401. Again in the same /login route, write:

Before going forward, let’s install another library called the jsonwebtoken.

$ npm install jsonwebtoken

At the top of the index.js file, write the require statement for the jsonwebtoken library as shown below:

const jwt = require("jsonwebtoken");

We will use this library to create a JSON Web Token for every valid user. To do this, we will create a new const called token using the sign method from the jsonwebtoken library. Note that we are still writing the code inside the /login route.

const token = jwt.sign({
  sub: user.id,
  username: user.username
}, "mykey", {expiresIn: "3 hours"});
res.status(200).send({access_token: token})

Now go to POSTMAN, and send a post request with the following JSON object in its body.

{
  "username": "clarkKent",
  "password": "superman",
}

The result will be a JSON Web Token as shown below:

If you copy the value of access_token into the JWT.IO Debugger, you will see that it is the same username and password, but with a few extra things.

Side note — CORS

In some cases where the API that your app tries to access is running on a different server than that of your app’s, will return some kind of *Failed To Load *error.

To prevent this from happening, we can install another library called cors

$ npm install cors

Then at the top of the index.js file, write the require statement for this library as shown below:

const cors = require("cors");

Then similar to what we did with the body-parser library, we will tell the express to use cors as shown below:

app.use(cors());

Provide User Access To An API using JWT

Here, we will create a new API with two routes. The first route will be public, while the second one will require the user to be authenticated using *JWT *into order to access it.

Let’s create a new file in the jwt-auth folder called api.js. In this file, write the following startup code:

const express = require("express");
const bodyParser = require("body-parser"); 
const app = express();
const PORT = process.env.API_PORT || 8888;
app.use(bodyParser.json());   
app.get("*", (req, res) => {    
  res.sendStatus(404);
}); 
app.listen(PORT, () => {    
  console.log(`Server is running on port ${PORT}.`);
});

Let’s create a new route called '/asset. This will be public route that I had mentioned earlier, and will simply return a status code 200.

app.get("/asset", (req, res) => {
  res.status(200).send("Everybody can see this");
});

The second, secret route will be /asset/secret and it will be secured with a jwtCheck as shown below:

app.get("/asset/secret", jwtCheck, (req, res) => {
  res.status(200).send("Only logged in people can see me");
});

Since the index.js file is set to run on the PORT 8888, we need to set some other PORT for this file. To do that, open the command terminal and run the command:

$ export API_PORT=5555

Even though we have said that the /asset/secret route is secure, we haven’t actually implemented it. To do so, we need to install another middleware library called express-jwt.

$ npm install express-jwt

Then at the top of api.js file, write the require statement for this library.

const expressjwt = require("express-jwt");

We will use this library to define the jwtCheck. We will use jwtCheck to check if the signature matches the one that we got from our authentication server. If you recall, we have named it as “mykey”.

const jwtCheck = expressjwt({    
  secret: "mykey"
});

Run the node api.js command in your terminal. To check if the authentication works as it should, go to POSTMAN and run the GET request on localhost:5000/asset. The response should be Everybody can see this.

Then run the GET request on localhost:5000/asset/secret. What you should get is a big error code that looks something like this:

To solve this, go to the Authentication tab in POSTMAN, and select the Type as Bearer Token. Then enter the value of Token as the one that we had received in the previous sections.

Conclusion

Compared to other web tokens like Simple *Web Tokens (SWTs) *or Security Assertion Markup Language (SAML), *JWT *is much simpler as it is based on *JSON *which is easier to understand than XML.

If we encode the JSON, it will become even more smaller in size than SAML, making it easier to pass in HTML and HTTP environments.

Security wise, SWTs use a single key, whereas both JWT and SAML use a public and private key pair for better authentication.

Talking from a usage point of view, JWTs are used at Internet scale. This means that it is easier to process on the user’s devices, be it laptops or mobile.

Apart from authenctication, JSON Web Token are a great and secure way of transmitting data between multiple parties. The fact that JWTs have signatures makes it easier for everyone to easily identify the sender of information. All you need is the correct key.

Thanks for reading! I hope this post helped you understand how to implement a simple JSON Web Token Authentication in your application. Feel free to comment and ask/suggest anything!

javascript web-development security json

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Why Web Development is Important for your Business

With the rapid development in technology, the old ways to do business have changed completely. A lot more advanced and developed ways are ...

Best Custom Web & Mobile App Development Company

Top Web & Mobile Application Development Company in India & USA. We specialize in Golang, Ruby on Rails, Symfony, Laravel PHP, Python, Angular, Mobile Apps, Blockchain, & Chatbots

Hire Dedicated eCommerce Web Developers | Top eCommerce Web Designers

Build your eCommerce project by hiring our expert eCommerce Website developers. Our Dedicated Web Designers develop powerful & robust website in a short span of time.

How long does it take to develop/build an app?

This article covers A-Z about the mobile and web app development process and answers your question on how long does it take to develop/build an app.

Progressive Web App Development

Hire Full Stack Developer from HireFullStackDeveloperIndia.com to build user-centric & robust Progress Web App Development Solutions in India.