AppDividend
Latest Code Tutorials

How To Create Node JWT Authentication System Example

20

Node JWT Authentication Tutorial is the topic we will discuss today. The full form of JWT is JSON Web Token. If we want to build a secure web application, then we have to implement Authentication. After that, we need to develop Authorization. There are two types of Authentication you can use in any web application development.

  1. Session-based Authentication
  2. Token-based Authentication

JWT-based User Sessions

Let’s start by introducing how JSON Web Tokens can be used to establish a user session: in a nutshell, JWTs are digitally signed JSON payloads, encoded in a URL-friendly string format.

A JWT can contain any payload in general, but the most common use case is to use the payload to define a user session.

The key thing about JWTs is that to confirm if they are valid, we only need to inspect the token itself and validate the signature, without having to contact a separate server for that, or keeping the tokens in memory or the database between requests.

If JWTs are used for Authentication, they will contain at least a user ID and an expiration timestamp.

If you are curious to know what a JWT looks like, here is an example:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

To see it what is the payload in the above token, let’s head over to jwt.io and paste the complete JWT string into the validation tool, we will then see the JSON Payload.

The sub property contains the user identifier, and the user property contains the user. This type of token is known as a Bearer Token, meaning that it identifies the user that owns it, and defines a user session.

A bearer token is a signed temporary replacement for the username/password combination!

If you would like to learn further about JWTs, have a look here. For the remainder of this post, we will assume that a JWT is a string containing a valid JSON payload, which defines a user session.

The very first step for implementing JWT-based Authentication is to issue a bearer token and give it to the user, and that is the primary purpose of a Login / Sign up page.

JWT Token-based Authentication

In today’s topic, we will use Token-based Authentication. If you want to learn Session-based Authentication, then check out my Simple Nodejs Authentication System Using Passport article. I have briefly described Session-based Authentication in that article. 

JWT authentication is becoming very popular these days.

The traditional authentication uses cookies and sessions. With the advent of Single Page Applications(SPA) and microservices, there is a need to look beyond the sessions. Any token-based authentication serves that purpose.

JWT is a type of token-based authentication. For every single request from a client to the server, a token is passed for authentication.

Most importantly, it supports stateless API calls.

Token-based authentication is everywhere on the web nowadays. With almost every web company using an API, token authentication is the best way to handle authentication for multiple users.

Why we use Token-based Authentication

Session-based authentication is fine, then why we want to use Token-based Authentication? The reasons are the following.

  1. A primary reason is that it is Stateless Authentication.  This token is stored client-side local storage but can be stored in session storage or a cookie as well.
  2. Its most use cases are single-page applications, web APIs, and the Internet of Things (IoT).
  3. If our application is scalable and decoupled, then it is the best choice to use this de-facto standard.
  4. It is a mobile-ready and web application prepared regardless of which technologies you are using to build your web and mobile app.
  5. Convenient: Using a JWT for authentication to the back end once logged in requires setting one HTTP header, a task that can be easily automated through a function or subclassing, as we’ll see later.
  6. Compact: A token is simply a base64-encoded string, containing a few header fields, and a payload if required. The total JWT is usually less than 200 bytes, even if signed.
  7. Secure: While not required, a great security feature of JWT is that tokens can be signed using either RSA public/private key-pair encryption or HMAC encryption using a shared secret. This ensures the origin and validity of a token.

What this all boils down to is that you have a secure and efficient way to authenticate users, and then verify calls to your API endpoints without having to parse any data structures nor implement your encryption.

How JWT(JSON Web Tokens) Works?

JSON web tokens are text strings that can be used by the client and servers to authenticate and share information effortlessly.

If you remember the necessary authentication, we do write information to the client by writing the cookie as a session variable.

However, in JWT, a token is encoded from a data payload using a secret. That token is passed to the client. Whenever the client sends that token along with a request, the server validates it and sends back the response. See this diagram for a clear picture.

Node js API JWT Authentication Tutorial

JSON Web Token is the token; we need to put the header in every request to verify the client. The Architecture of JWT Authentication is pretty darn simple.

  1. The first user attempts to log in with their credentials.
  2. After the server verifies the credentials, the server generates and sends the JSON Web Token to the client.
  3. A client then saves that token in local storage or any other storage mechanism.
  4. Again if a client wants to request a protected route or resource, then it sends JWT in a request header.
  5. The server verifies that JWT and if it is correct, then return a 200 response with the information, client needs.
  6. If the JWT is invalid, then it gives unauthorized access or any other restricted message.

You might be wondering, ‘Everything is clear to me except how the server is generating JWT?’. JWT token creation is a vast and beautiful topic, and you get a whole lot of details here. https://jwt.io/introduction/

After reading that whole algorithm to generate tokens, you might be tempted to write your functionality.

Hold on! There are many libraries available in different languages developed already. You plug them, and you get two main functionalities to generating JWT, validate JWT, etc.

Here I pick an NPM library called jsonwebtoken, which is suggested by the JWT website rather than re-inventing the wheel.

Node JWT Authentication Example

In this tutorial, we are not using any front-end framework. We will use POSTMAN  to request the server. We will check the auth using the token. So let us get started.

Step 1: Install node js dependencies.

Create one project folder and go into that folder. Type the following command.

npm init

Now, install the following dependencies.

npm install express jsonwebtoken mongoose body-parser --save

It will install the Express web framework, jsonwebtoken package to authenticate the user, mongoose schema model, and body-parser middleware.

Also, we need to install the nodemon development server to prevent the stop and restart the server process. So let us do that first.

npm install nodemon --save-dev

Rest dependencies, and we will install as our project grows.

Step 2: Configure the Node Server.

In the package.json file, change this object to the following.

"scripts": {
    "start": "nodemon server"
},

So in the terminal, when we type npm start command, we bootstrap the server.js file.
In the root folder, make one file called server.js. Configure the node server.

// server.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');


const PORT = 3000;

app.listen(PORT, function(){
   console.log('Server is running on Port',PORT);
});

Now, go to the terminal and hit the following instruction.

npm start

It will start the server, you can see it on a console. So it is ready to consume any request, either web or API.

Step 3: Send a request to node server via Postman.

First, we define one route and send the JSON response to the client.

// server.js

app.get('/checking', function(req, res){
   res.json({
      "Tutorial": "Welcome to the Node express JWT Tutorial"
   });
});

Open the Postman and send the get request to http://localhost:3000/checking.

Postman Tutorial

Step 4: Configure the MongoDB Database.

Write the following code to connect the Node.js application to the MongoDB database.

// server.js

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/jwtauth');

Also, write the body-parser middleware to the application.

// server.js

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

Step 5: Create a User model.

Create one new folder inside the root called models. In that, create one file called user.model.js file.

// user.model.js

const mongoose = require('mongoose');

const user = mongoose.Schema({
   _id: mongoose.Schema.Types.ObjectId,
   email: {type: String, required: true},
   password: {type: String, required: true}
});

module.exports = mongoose.model('User', user);

We have defined the schema for the User collection.

Step 6: Create routes for users.

In the root, make one folder called routes. In that folder, create one file called user.route.js. Now we need to sign the user up for our application. So let us define the post route to signup the user.

We also need a bcrypt module to hash the password. We can not store the plain password. So let us install the bcrypt module first.

npm install bcrypt --save

Next, write the following code into the user.route.js file.

// user.route.js

const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const User = require('../models/user.model');

router.post('/signup', function(req, res) {
   bcrypt.hash(req.body.password, 10, function(err, hash){
      if(err) {
         return res.status(500).json({
            error: err
         });
      }
      else {
         const user = new User({
            _id: new  mongoose.Types.ObjectId(),
            email: req.body.email,
            password: hash    
         });
         user.save().then(function(result) {
            console.log(result);
            res.status(200).json({
               success: 'New user has been created'
            });
         }).catch(error => {
            res.status(500).json({
               error: err
            });
         });
      }
   });
});

module.exports = router;

What it does is that it tries to hash the incoming request’s password property. If it fails to do so, then returns a response with an error in json format.

If it successes, then it will create a new user and add that to the MongoDB database. Now include this user.route.js file in the server.js file. I am writing the whole file now.

// server.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const user = require('./routes/user.route');
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/jwtauth');

const PORT = 3000;

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('/checking', function(req, res){
   res.json({
      "Tutorial": "Welcome to the Node express JWT Tutorial"
   });
});

app.use('/user', user);

app.listen(PORT, function(){
   console.log('Server is running on Port',PORT);
});

Step 7: Send a post request from the Postman.

Open the postman send a request in a row format with application type json(application/json).

Node js API Authentication Tutorial

You can see here, I have created users successfully. Now, I am using Studio 3T for MongoDB. So here is the newly created user in the database.

MongoDB Tutorial With An Example

Step 8: Sign In the User.

Go to the user.route.js file and define the signin route.

// user.route.js

router.post('/signin', function(req, res){
   User.findOne({email: req.body.email})
   .exec()
   .then(function(user) {
      bcrypt.compare(req.body.password, user.password, function(err, result){
         if(err) {
            return res.status(401).json({
               failed: 'Unauthorized Access'
            });
         }
         if(result) {
            return res.status(200).json({
               success: 'Welcome to the JWT Auth'
            });
         }
         return res.status(401).json({
            failed: 'Unauthorized Access'
         });
      });
   })
   .catch(error => {
      res.status(500).json({
         error: error
      });
   });;
});

First, I have checked if the user’s email exists or not. If not, then return 401 unauthorized access. If email is there, then check the password with encrypted database password if match found then welcome to the JWT auth else 401 unauthorized access.

Node js Auth APIIf the Authentication Attempt is not successful, then we will get the following error.

Express Node js Auth API Tutorial

Step 9: Return the JWT, if auth attempt successful.

We have several different ways of sending the token back to the user, for example:

  1. In a Cookie
  2. In the HTTP response body
  3. In a plain HTTP Header

JWTs and Cookies

Let’s start with cookies, why not use them? JWTs are sometimes mentioned as an alternative to Cookies, but these are two very different concepts. Cookies are a browser data storage mechanism, a place where we can safely store a small amount of data.

That data could be anything such as for example the user preferred language, but it can also contain a user identification token such as for example a JWT.

So we can, for example, store a JWT in a cookie! Let’s then talk about the advantages and disadvantages of using cookies to store JWTs, when compared to other methods.

Sending the JWT back in the HTTP response body

Cookies with their unique HTTP Only property are a solid choice for storing JWTs, but there are other good choices available. For example, instead of cookies, we are going to send the JWT back to the client in the HTTP Response body.

Not only do we want to send back the JWT itself, but it’s better to send also the expiration timestamp as separate property.

It’s true that the expiration timestamp is also available inside the JWT, but we want to make it simple for the client to obtain the session duration without having to install a JWT library just for that.

We will go for sending the JWT token in the response body.

If the user’s credentials email and password are valid, then in response, we need to return a JWT token. So let us generate the token and return to the user.

// user.route.js

const jwt = require('jsonwebtoken');

if(result) {
   const JWTToken = jwt.sign({
        email: user.email,
        _id: user._id
      },
      'secret',
       {
         expiresIn: '2h'
       });
       return res.status(200).json({
         success: 'Welcome to the JWT Auth',
         token: JWTToken
       });
  }

The format of the JWT Token is as following.

HEADER: ALGORITHM & TOKEN TYPE

{
“alg”: “HS256”,
“typ”: “JWT”
}

PAYLOAD:DATA

{
“email”: “krunallathiya10@gmail.com”,
“_id”: “5a7c9bd8fc3e501c94aa6035”,
“iat”: 1518120124,
“exp”: 1518127324
}

VERIFY SIGNATURE

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

So it is a combination of header, payload, and secretkey, we are providing. Remember, You need to define your secret key in your environment variable file. I have just shown here for the demo purpose. So it will produce the following JWT token.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImtydW5hbGxhdGhpeWExMEBnbWFpbC5jb20iLCJfaWQiOiI1YTdjOWJkOGZjM2U1MDFjOTRhYTYwMzUiLCJpYXQiOjE1MTgxMjAxMjQsImV4cCI6MTUxODEyNzMyNH0._6qVGQV_KYlonawnaTHG-OhOJLV4tgD-Eob5iRz89AM

JWT Token Tutorial

Now use this token to access the protected resources to your application.

Here, we are almost done with the Node JWT Authentication article. Now, there are some client-side operations we need to do.

Storing and using the JWT on the client-side

Once we receive the JWT on the client, we need to store it somewhere, otherwise, it will be lost if we refresh the browser and would have to log in again.

There are many places where we could save the JWT (other than cookies). A practical place to store the JWT is on Local Storage, which is a key/value store for string values that is ideal for storing a small amount of data.

Note that Local Storage has an asynchronous API. Let’s have a look at an implementation of the login/logout logic using Local Storage.

Sending The JWT to the server on each request

Now that we have the JWT saved in the user browser, let’s keep tracking its journey through the network.

Let’s see how we are going to use it to tell the Application server that a given HTTP request belongs to a given user, which is the whole point of the Authentication solution.

Here is what we need to do: we need with each HTTP request sent to the Application server, to somehow also append the JWT!

The application server is then going to validate the request and link it to a user, simply by inspecting the JWT, checking its signature and reading the user identifier from the payload.

Finally, our Node JWT Authentication Example From Scratch is over. I have put this code on Github as well.

I have out Node JWT Authentication project code on Github. Please do check it out.

Fork Me On Github

20 Comments
  1. robbin says

    Cool. Thx, will try it out. ?

  2. Robert says

    Nice Tutorial! Thanks!

  3. XAvi says

    very good, it served me very much thanks

  4. Muhammad Riza says

    this helps me so much, thank you!

  5. Himanshu says

    High five

  6. Hugo says

    Thank You sir !!

    1. Krunal says

      Your welcome!!

  7. Boopathi says

    Hello sir,
    very nice tutorial i can understand but how to protect all the routes, can you tell me sir.

  8. Winlight says

    Hi, since the whole js world is moving to ES6 can you please convert this to ES6!

  9. karim says

    thank you !! simple , clear , and easy !

  10. James Slattery says

    I’m having an issue with signin and comparing passwords. The password from the request body is unencrypted and the password from the user documents is encrypted. How/when does the password in the request body get encrypted?

  11. prashant says

    This information is so useful to learn about JWT. Thanks a lot.

  12. raja saini says

    thanks a lot you gave me a idea about jwt, very easy documentation

  13. Bob says

    Very good, simple efficient nice

  14. Winlight Solutions says

    Nice tutorial, well done, need to start converting it to ES6 though and also it would be even better if you could put up a “How to use this with a Frontend (Angular)”!.

  15. Sulav says

    I am using postgresql. What can be used instead of findOne in sign in for this?

  16. Nguyễn Việt Hưng says

    Thank you

  17. Danushka Herath says

    Woooow! High Five

  18. Dany says

    Thank you, I’m grateful to have found this tutorial. And i will try your tutorial authentication using pasport for the next.

  19. Hai says

    good

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.