How to implement JWT Authentication in Node-js API

How to implement JWT Authentication in Node-js API

In this tutorial we'll go through a simple example of making a simple **Node.js API** and then we will be applying some kind of Authentication with the help of JWT.

In this post, I will be introducing to you JWT (JSON Web Tokens) Technology which lets you do http requests with protected access i.e. some kind of token is returned in the JSON response. And with the help of this token you will be making the request. After getting the token you can save the token to Cookies (Not Recommended anymore) but you can save these tokens to LocalStorage. The upcoming requests you make to the server will contain the header with this web token. In this tutorial we will be making a simple Node.js API and then we will be applying some kind of Authentication with the help of JWT. Let’s get started with the post.

Examples of JWT

Some of the noteworthy examples where you can find these JWT being used are the OAuth login systems of various social media sites such as google, facebook , github, twitter etc. When you make a OAuth request you need to get a access token to request user data from the social media provider. Similarly they uses JWT under the hood to implement this functionalty. Now in this blog post we will making our own system i.e. own api, making requests to the api to access the data. And in the process we will be implementing Authentication to that data so that only users have the JWT can access the API.

Prerequisites
  1. Basic Knowledge of Node is required.
  2. Basic Knowledge of Postman is required.
Requirements
  1. Postman : It will be the tool from which we will making our requests. You can download the tool from here
  2. Visual Studio Code : It will be the Text Editor on which we will be writing our code.
  3. Node : You should have node installed on to your computer.
Postman

Postman is GUI Tool for both mac,windows and linux to make HTTP requests to the server. It makes the job more easier by providing the right tools to make HTTP requests. As you know curl and more command prompt tools are so cumbersome to use. You can see the look of postman given below. How beautiful is the interface of the tool.

Here you can see in the above figure we can send requests by specifying the URL property in the input textfield. Apart from that we have also the option to add additional HTTP headers on that request.

Creating Project

First of all create a new directory where you will create your node project. Enter the directory after creating it and open command line inside the directory and issue this command which is shown below.

After executing this command npm init it will ask you some questions about the project that what name you want to give your project, description of project, author name, license and all that stuff. Just go through that and lastly it will create the package.json file from the data you provided earlier. So the package json file will look like something like this.

This contains all the information about your project. Now the next thing we need to do is install some dependencies which will be required to make this project.

Installing Dependencies
  1. Nodemon: First of all we will install Nodemon it is required because we don’t want to restart server again and again when any kind of change is made to the application. It will automatically do that task for us. This will be a dev depedency (Development Dependency).

After installing it successfully. Now just start the nodemon server something like this

Actually index.js will be our main startpoint script file. Here we are just starting it. Obviously we will write code

in it later.

  1. Installing Express & JWT :  Now we will install the two main dependencies of the project. Just write this command as shown below.

After installing these dependencies the package.json file will look something like this

Now create a new index.js file and in that file we will write our code. And in that file first of all we will be importing the dependencies that we have installed earlier i.e. express and jwt. And then after that we will be starting our server at Port 5000 you can take any port number of your choice. In that port number the server will be receiving requests from the user. When the user requests the url at that port we will sending a json response back to the browser. In postman later we will see the response coming back from the api.

const express = require('express');

const jwt = require('jsonwebtoken');

const app = express();

app.get('/api',(req,res) =>{
    res.json({
        message:'Welcome to the API'
    })
})

app.listen(5000,() => console.log('Server started on Port 5000'))

Now if we run this by writing nodemon index.js command in command prompt we will see the following output.

So our server started at Port 5000 as shown above. Now if we open the Postman Software and make a get request at the following url http://localhost:5000/api we shall get a json response back from the api something like this.

So you can see above we get a json response back from the api i.e. welcome to the api the same text that we have written in the code. So we can now make a basic send request to the api.

Similarly we can now make a post request to the api also. We will now write a post request in our code. We will not use in any kind of form but a simple post request for which we will returning some message.

app.post('/api/posts',(req,res) =>{
    res.json({
        message:'Post successfully created'
    })
})

So again when we open postman this time we will be selecting post in the method type and type this url http://localhost:5000/api/posts we shall receive a response something like this

So we get a similar json response post successfully created. Now we need to add some authentication to our api. So that not everyone can access our api. The authentication part will be handled by jwt library.

So first of all we will again create a post request but now we will have authentication attached to that request. In this first of all we will create a mock user through which we will be implementing authentication. You can also save users in a database and do authentication but for this simple tutorial we will create a random user and use that in it. So create a mock user something like this.

app.post('/api/login',(req,res) =>{
   const user ={
       id : 1,
       username: 'Gautam',
       email: '[email protected]'
   }

So this user has three fields you can see the id, username and email address. So after creating this we will calling the jwt sign method which takes the payload data in this case the user object, secondly it takes the secret key which you have to pass you can name anything you want but i have named secretkey just for easy understanding and lastly we have the callback function which will run if the authentication is successful. We have two variables err and token if authentication is not successful then error will be thrown which is stored inside err variable but if authentication is successful then the token will be returned in the json response whenever user hits the url.

jwt.sign({user:user},'secretkey',(err,token) =>{
       res.json({
           token:token
       })
   })

So after that if we run the application and open postman and send a post request to the url http://localhost:5000/api/login we shall get this result as shown below.

So you can see that a token is returned in the json response when we send the post request to the url. This token contains all the information that we will need to make a protected request to a route which we don’t have write now. Now we will create that route.

Now we will be moving back to the posts route that we have created earlier in the post. We will protect that route so that only authenticated users can access that route. For adding authentication we will be first of all adding the middleware function to that route something like this.

app.post('/api/posts',verifyToken,(req,res) =>{
    res.json({
        message:'Post successfully created'
    })
})

In this code we are calling the custom middleware function i.e. verifyToken. We will create this function now in this function we will be verifying the token which is generated earlier. This function takes req , res, and next which will continue from middleware to the actual post request.

function verifyToken(req,res,next)
{
}

The first thing we will do in this function is that we will be grabing the authorization header from the request. The Authorization header is actually Bearer {Actual Token}. Here Bearer is a term used in Authorization header. So we will be grabing the whole header and checking if it is undefined or not.

if(typeof bearerHeader !== 'undefined')
    {

    }else{
        res.sendStatus(403);
    }

If the Authorization header is undefined then we can simply send the response status to 403 i.e. forbidden. It actually means that we are saying to the user that the resource requested by the user doesn’t exist. Because you are not eligible to make the request i.e. you don’t have the token.

After this if the token is there with the user then we will split the token from the Bearer text something like this

const bearer = bearerHeader.split(' ');
      const bearerToken = bearer[1];
      req.token = bearerToken;
      next();

In this section of code we are first of all splitting the token and the bearer text with the help of split function. Split function actually splits the string into an array. In this case we are splitting the string by a space and then we have the array containing the bearer and the token in two indices. First indice holds the Bearer text and the second indice will hold the token. So we can access the token by bearer[1] as array starts from 0. Then after extracting the token we are setting the token to the request token and then we are calling the next function to continue from the middleware to the post request.

[

Now if we make a post request to http://localhost:5000/api/posts then it should return forbidden as shown below because now it is a protected resource

Now we will go back to the posts route and write some checks in order to verify that the token which is entered by the user is correct or not. So for that we will be using the JWT verify function which takes the actual token which is passed by req.token and the second argument will be the secretkey again and you can give any name of your choice and lastly we will be having two variables err and authdata which represents the error and the actual authdata which will be send in the json response which includes the id, username and email address if the authentication is successful. So if any kind of error takes place we will be sending the forbidden status code of 403. And if all goes right we will be sending the post message as well as the authdata.

app.post('/api/posts',verifyToken,(req,res) =>{

    jwt.verify(req.token,'secretkey',(err,authData) =>{
        if(err){
            res.sendStatus(403)
        }
        else{

            res.json({
                message:'Post successfully created',
                authData:authData
            })

        }
    })
})

Now if we make a postman post request to the login route then a token will be generated something like this

Now if we copy paste this token and send it as a Authorization header to the api/posts route then we shall get the authdata and post message

Now you can see that the json response includes the post message and the authdata which includes the user object which contains the id, username and email address of the user which we have created earlier. And also a issued at token is also generated which is actually a timestamp.

Now we can also add a expiration time to the token which is generated so that it can’t be there for all the time. It is very necessary for the applications to have the expiry time for the token. For this we will going back to the login route and edit the jwt sign method in that just add this expiresIn field and after that give how many seconds you want for token to expire. I am giving 30 seconds you can give any value of your choice.

jwt.sign({user:user},'secretkey',{expiresIn:'30s'},(err,token) =>{
       res.json({
           token:token
       })
   })

Now the Application is complete. Ofcourse we are using Postman but you can extend this application by using a front end such as Angular or Vuejs to make the http request. The full source code of the application is given below.

const express = require('express');

const jwt = require('jsonwebtoken');

const app = express();

app.get('/api',(req,res) =>{
    res.json({
        message:'Welcome to the API'
    })
})

app.post('/api/posts',verifyToken,(req,res) =>{

    jwt.verify(req.token,'secretkey',(err,authData) =>{
        if(err){
            res.sendStatus(403)
        }
        else{

            res.json({
                message:'Post successfully created',
                authData:authData
            })

        }
    })
})

app.post('/api/login',(req,res) =>{
   const user ={
       id : 1,
       username: 'Gautam',
       email: '[email protected]'
   }

   jwt.sign({user:user},'secretkey',{expiresIn:'30s'},(err,token) =>{
       res.json({
           token:token
       })
   })
})

function verifyToken(req,res,next)
{
    const bearerHeader = req.headers['authorization'];
    if(typeof bearerHeader !== 'undefined')
    {
      const bearer = bearerHeader.split(' ');
      const bearerToken = bearer[1];
      req.token = bearerToken;
      next();

    }else{
        res.sendStatus(403);
    }
}

app.listen(5000,() => console.log('Server started on Port 5000'))

Thank you for reading, Please share if you liked it!

Build A Node.js API Authentication With JWT Tutorial

Build A Node.js API Authentication With JWT Tutorial

In this episode we are going to create a node.js api that is going to handle Authentication for us in any application we want to use it in.

We are going to cover an authentication method using jwt. We will use mongodb as our database, mongoose to create models and to connect to our express server, bcryptjs to hash passwords and jwt to check for private routes.

📕 Things covered in this video:

00:00:57 Introduction

00:02:32 Setting up express

00:08:12 Connecting to a database

00:14:22 .env files

00:16:39 Creating models in mongoose

00:19:34 Registering a user

00:25:40 Validation with Joi

00:42:35 Hashing passwords

00:48:53 Setting up the login route

00:57:25 Adding jsonwebtokens to our auth

01:03:25 Creating private routes with jwt

How to Create a Fake REST API Server using Node.js

How to Create a Fake REST API Server using Node.js

How to make a REST API Server using Node.js for testing your AJAX client side.

In this post, I want to show you how to create a fake REST API Server, using Node.js. This will be just a Server to test AJAX at your client side. In addition to it, it added support for CORS and request verbs like (POST, GET, DELETE, PUT).

First of all, create a folder (RESTAPI)  and create a JSON file, as shown below. I used the file mentioned in the link above for sample JSON data.

{  
   "user1" : {  
      "name" : "mahesh",  
      "password" : "password1",  
      "profession" : "teacher",  
      "id": 1  
   },  
   "user2" : {  
      "name" : "suresh",  
      "password" : "password2",  
      "profession" : "librarian",  
      "id": 2  
   },  
   "user3" : {  
      "name" : "ramesh",  
      "password" : "password3",  
      "profession" : "clerk",  
      "id": 3  
   }  
}  

From start menu, open Node.Js command prompt and change the directory, where our folder is located and type the command given below.

npm install express --save

Create a JavaScript file, add the piece of code and name it server.js.

var express = require('express');  
var app = express();  
var fs = require("fs");  
var bodyParser = require('body-parser');  
  
//enable CORS for request verbs
app.use(function(req, res, next) {  
  res.header("Access-Control-Allow-Origin", "*");  
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");  
  res.header("Access-Control-Allow-Methods","POST, GET, PUT, DELETE, OPTIONS");  
  next();  
});  
  
app.use(bodyParser.urlencoded({  
    extended: true  
}));  
  
app.use(bodyParser.json());  
  
//Handle GET method for listing all users
app.get('/listUsers', function (req, res) {  
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       console.log( data );  
       res.end( data );  
   });  
})  
  
//Handle GET method to get only one record
app.get('/:id', function (req, res) {  
   // First read existing users.  
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       users = JSON.parse( data );  
       console.log(req.params.id);  
       var user = users["user" + req.params.id]   
       console.log( user );  
       res.end( JSON.stringify(user));  
   });  
})  
  
//Handle POST method
app.post('/addUser', function (req, res) {  
   // First read existing users.  
       fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       var obj = JSON.parse('[' + data + ']' );  
       obj.push(req.body);  
       console.log(obj);  
         
       res.end( JSON.stringify(obj)  );  
   });  
})  
  
//Handle DELETE method
app.delete('/deleteUser/:id', function (req, res) {  
  
   // First read existing users.  
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       data = JSON.parse( data );  
         
       delete data["user" + req.params.id];  
         
       console.log( data );  
       res.end( JSON.stringify(data));  
   });  
})  
  
//Handle GET method
app.put('/updateUser/:id', function(req,res){  
      
    // First read existing users.  
    fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       //var obj = JSON.parse('[' + data + ']' );  
       data = JSON.parse( data );  
       var arr={};  
       arr=req.body;  
         
        data["user" + req.params.id]= arr[Object.keys(arr)[0]] ; //  req.body;   //obj[Object.keys(obj)[0]]  
          
        res.end( JSON.stringify( data ));  
         
    });  
} );  
  
var server = app.listen(8081, function () {  
  
  var host = server.address().address  
  var port = server.address().port  
  
  console.log("Example app listening at http://%s:%s", host, port)  
  
})  

Notice

The parameter (data) of the request handler method is supposed to be an array of JSON objects but it didn't accept the normal array methods like (push) method, so I decided to parse it with the brackets [ ].

var obj = JSON.parse('[' + data + ']' );     

To run this Server, open node.js command prompt and run the command.

$ node server.js

Now, the Server is running and now you have a REST API Server, which supports CORS for the requests.

Here, it is listening at port 8081. To test our Server, this is the sample data for the testing purpose.

Here, it is listening at port 808. To test our Server, this is a sample data for the testing purpose.

I hope it comes in handy. Thank you for reading !

How to Create Secure (JWT) Token Based Authentication API with Node.js

How to Create Secure (JWT) Token Based Authentication API with Node.js

In this tutorial, we are going to learn how to build a secure token-based user authentication REST APIs using JWT (JSON web token), bcrypt, Node, Express, and MongoDB

Creating authentication REST API with Node Js is merely effortless. We will be taking the help of Express js to create the authentication endpoints and also make the MongoDB connection to store the user’s data in it.

Authentication Workflow with JSON Web Tokens

Let’s understand from the below diagram how does the secure authentication system work with JSON web token.

  • A client makes the API call and sends the user information such as username and password to the webserver.
  • On successful authentication a webserver generates a string-based token and returns to the client system.
  • A client can store this token in the browser’s local storage or in a session.
  • Client sets this token in a header something like “Bearer xxx.xxx.xxx”.
  • On next API call JWT token communicateS with the server, and after the successful verification, the server returns the response to the client.
Initiate Node Token-Based Authentication Project

Create a project folder to build secure user authentication REST API, run the following command.

mkdir server

Get inside the project folder.

cd server

Let’s start the project by first creating the package.json file by running the following command.

npm init

Install NPM Packages to Create Secure Auth API

Next, install the NPM dependencies for the authentication API by running the given below command.

npm install express jsonwebtoken bcryptjs body-parser 
cors mongoose-unique-validator mongoose --save

Next, install the nodemon NPM module, it helps in starting the node server when any change occurs in the server files.

npm install nodemon --save-dev
Define Mongoose Schema

Next, we are going to define user schema using mongoose ODM. It allows us to retrieve the data from the database.

Create a folder and name it models inside the project directory, create a file User.js in it.

To prevent storing the duplicate email id in MongoDB database install mongoose-unique-validator package. Below we will learn how to use in mongoose schema to validate duplicate email id from MongoDB database.

npm i mongoose-unique-validator --save

Next, add the following code in models/User.js file:

// models/User.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const uniqueValidator = require('mongoose-unique-validator');

let userSchema = new Schema({
    name: {
        type: String
    },
    email: {
        type: String,
        unique: true
    },
    password: {
        type: String
    }
}, {
    collection: 'users'
})

userSchema.plugin(uniqueValidator, { message: 'Email already in use.' });
module.exports = mongoose.model('User', userSchema)
  • The userSchema.plugin(uniqueValidator) method won’t let duplicate email id to be stored in the database.
  • The unique: true property in email schema does the internal optimization to enhance the performance.
Implement MongoDB Database in Node App

Create database folder in the project folder and create a new file database/db.js in it.

module.exports = {
    db: 'mongodb://localhost:27017/meanauthdb'
}
Create Secure Token-based Authentication REST API in Node

To build secure user authentication endpoints in node, create routes folder, and auth.routes.js file in it.

Here, we will define CRUD Restful APIs using the npm packages for log-in, sign-up, update-user, and delete-user.

// routes/auth.routes.js

const express = require("express");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const router = express.Router();
const userSchema = require("../models/User");

// Sign-up
router.post("/register-user", (req, res, next) => {
    bcrypt.hash(req.body.password, 10).then((hash) => {
        const user = new userSchema({
            name: req.body.name,
            email: req.body.email,
            password: hash
        });
        user.save().then((response) => {
            res.status(201).json({
                message: "User successfully created!",
                result: response
            });
        }).catch(error => {
            res.status(500).json({
                error: error
            });
        });
    });
});

// Sign-in
router.post("/signin", (req, res, next) => {
    let getUser;
    userSchema.findOne({
        email: req.body.email
    }).then(user => {
        if (!user) {
            return res.status(401).json({
                message: "Authentication failed"
            });
        }
        getUser = user;
        return bcrypt.compare(req.body.password, user.password);
    }).then(response => {
        if (!response) {
            return res.status(401).json({
                message: "Authentication failed"
            });
        }
        let jwtToken = jwt.sign({
            email: getUser.email,
            userId: getUser._id
        }, "longer-secret-is-better", {
            expiresIn: "1h"
        });
        res.status(200).json({
            token: jwtToken,
            expiresIn: 3600,
            msg: getUser
        });
    }).catch(err => {
        return res.status(401).json({
            message: "Authentication failed"
        });
    });
});

// Get Users
router.route('/').get((req, res) => {
    userSchema.find((error, response) => {
        if (error) {
            return next(error)
        } else {
            res.status(200).json(response)
        }
    })
})

// Get Single User
router.route('/user-profile/:id').get((req, res, next) => {
    userSchema.findById(req.params.id, (error, data) => {
        if (error) {
            return next(error);
        } else {
            res.status(200).json({
                msg: data
            })
        }
    })
})

// Update User
router.route('/update-user/:id').put((req, res, next) => {
    userSchema.findByIdAndUpdate(req.params.id, {
        $set: req.body
    }, (error, data) => {
        if (error) {
            return next(error);
            console.log(error)
        } else {
            res.json(data)
            console.log('User successfully updated!')
        }
    })
})

// Delete User
router.route('/delete-user/:id').delete((req, res, next) => {
    userSchema.findByIdAndRemove(req.params.id, (error, data) => {
        if (error) {
            return next(error);
        } else {
            res.status(200).json({
                msg: data
            })
        }
    })
})

module.exports = router;
  • To secure the password, we are using the bcryptjs, It stores the hashed password in the database.
  • In the signin API, we are checking whether the assigned and retrieved passwords are the same or not using the bcrypt.compare() method.
  • In the signin API, we set the JWT token expiration time. Token will be expired within the defined duration.
Verify Node Authentication REST API

Next, we will verify the auth API using the JWT token. Create a middlewares folder and create a auth.js file inside of it, then include the following code in it.

Note: In the real world app the secret should not be kept in the code as declared below. The best practice is to store as an environment variable and it should be complex combination of numbers and strings.

// middlewares/auth.js

const jwt = require("jsonwebtoken");

module.exports = (req, res, next) => {
    try {
        const token = req.headers.authorization.split(" ")[1];
        jwt.verify(token, "longer-secret-is-better");
        next();
    } catch (error) {
        res.status(401).json({ message: "Authentication failed!" });
    }
};

Now, we will learn to implement JWT verification in the /user-profile endpoint. Import the following auth.js file from middlewares folder.

// Get User Profile
router.route('/user-profile/:id').get(authorize, (req, res, next) => {
    userSchema.findById(req.params.id, (error, data) => {
        if (error) {
            return next(error);
        } else {
            res.status(200).json({
                msg: data
            })
        }
    })
})

We added the authorize variable inside the user-profile API. It won’t render the data unless it has the valid JWT token. As you can see in the below screenshot, we have not defined the JWT token in get request, so we are getting the “No token provided” error.

Adding Input Validation in Express RESTful API

Next, we will learn to implement validation in Express auth API using POST body request. Install express-validator npm library to validate name, email and password.

The express-validator is an express.js middleware for validating POST body requests.

Run the below command to install the express-validator package.

npm install express-validator --save

Add the following code in the middlewares/auth.routes.js file.

// routes/auth.routes.js

const express = require("express");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const router = express.Router();
const userSchema = require("../models/User");
const authorize = require("../middlewares/auth");
const { check, validationResult } = require('express-validator');

// Sign-up
router.post("/register-user",
    [
        check('name')
            .not()
            .isEmpty()
            .isLength({ min: 3 })
            .withMessage('Name must be atleast 3 characters long'),
        check('email', 'Email is required')
            .not()
            .isEmpty(),
        check('password', 'Password should be between 5 to 8 characters long')
            .not()
            .isEmpty()
            .isLength({ min: 5, max: 8 })
    ],
    (req, res, next) => {
        const errors = validationResult(req);
        console.log(req.body);

        if (!errors.isEmpty()) {
            return res.status(422).jsonp(errors.array());
        }
        else {
            bcrypt.hash(req.body.password, 10).then((hash) => {
                const user = new userSchema({
                    name: req.body.name,
                    email: req.body.email,
                    password: hash
                });
                user.save().then((response) => {
                    res.status(201).json({
                        message: "User successfully created!",
                        result: response
                    });
                }).catch(error => {
                    res.status(500).json({
                        error: error
                    });
                });
            });
        }
    });

// Sign-in
router.post("/signin", (req, res, next) => {
    let getUser;
    userSchema.findOne({
        email: req.body.email
    }).then(user => {
        if (!user) {
            return res.status(401).json({
                message: "Authentication failed"
            });
        }
        getUser = user;
        return bcrypt.compare(req.body.password, user.password);
    }).then(response => {
        if (!response) {
            return res.status(401).json({
                message: "Authentication failed"
            });
        }
        let jwtToken = jwt.sign({
            email: getUser.email,
            userId: getUser._id
        }, "longer-secret-is-better", {
            expiresIn: "1h"
        });
        res.status(200).json({
            token: jwtToken,
            expiresIn: 3600,
            _id: getUser._id
        });
    }).catch(err => {
        return res.status(401).json({
            message: "Authentication failed"
        });
    });
});

// Get Users
router.route('/').get((req, res) => {
    userSchema.find((error, response) => {
        if (error) {
            return next(error)
        } else {
            res.status(200).json(response)
        }
    })
})

// Get Single User
router.route('/user-profile/:id').get(authorize, (req, res, next) => {
    userSchema.findById(req.params.id, (error, data) => {
        if (error) {
            return next(error);
        } else {
            res.status(200).json({
                msg: data
            })
        }
    })
})

// Update User
router.route('/update-user/:id').put((req, res, next) => {
    userSchema.findByIdAndUpdate(req.params.id, {
        $set: req.body
    }, (error, data) => {
        if (error) {
            return next(error);
            console.log(error)
        } else {
            res.json(data)
            console.log('User successfully updated!')
        }
    })
})

// Delete User
router.route('/delete-user/:id').delete((req, res, next) => {
    userSchema.findByIdAndRemove(req.params.id, (error, data) => {
        if (error) {
            return next(error);
        } else {
            res.status(200).json({
                msg: data
            })
        }
    })
})

module.exports = router;

We Passed the validation array with the check() method inside the post() method as a second argument. Next, we called the validationResult() method to validate errors, and it returns the errors if found any.

Following validation we implemented in ("/register-user") api.

  • Check if the value is required.
  • Check min and max character’s length.

Final auth.routes.js

// routes/auth.routes.js

const express = require("express");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const router = express.Router();
const userSchema = require("../models/User");
const authorize = require("../middlewares/auth");
const { check, validationResult } = require('express-validator');

// Sign-up
router.post("/register-user",
    [
        check('name')
            .not()
            .isEmpty()
            .isLength({ min: 3 })
            .withMessage('Name must be atleast 3 characters long'),
        check('email', 'Email is required')
            .not()
            .isEmpty(),
        check('password', 'Password should be between 5 to 8 characters long')
            .not()
            .isEmpty()
            .isLength({ min: 5, max: 8 })
    ],
    (req, res, next) => {
        const errors = validationResult(req);
        console.log(req.body);

        if (!errors.isEmpty()) {
            return res.status(422).jsonp(errors.array());
        }
        else {
            bcrypt.hash(req.body.password, 10).then((hash) => {
                const user = new userSchema({
                    name: req.body.name,
                    email: req.body.email,
                    password: hash
                });
                user.save().then((response) => {
                    res.status(201).json({
                        message: "User successfully created!",
                        result: response
                    });
                }).catch(error => {
                    res.status(500).json({
                        error: error
                    });
                });
            });
        }
    });

// Sign-in
router.post("/signin", (req, res, next) => {
    let getUser;
    userSchema.findOne({
        email: req.body.email
    }).then(user => {
        if (!user) {
            return res.status(401).json({
                message: "Authentication failed"
            });
        }
        getUser = user;
        return bcrypt.compare(req.body.password, user.password);
    }).then(response => {
        if (!response) {
            return res.status(401).json({
                message: "Authentication failed"
            });
        }
        let jwtToken = jwt.sign({
            email: getUser.email,
            userId: getUser._id
        }, "longer-secret-is-better", {
            expiresIn: "1h"
        });
        res.status(200).json({
            token: jwtToken,
            expiresIn: 3600,
            msg: getUser
        });
    }).catch(err => {
        return res.status(401).json({
            message: "Authentication failed"
        });
    });
});

// Get Users
router.route('/').get(authorize, (req, res) => {
    userSchema.find((error, response) => {
        if (error) {
            return next(error)
        } else {
            res.status(200).json(response)
        }
    })
})

// Get Single User
router.route('/user-profile/:id').get((req, res, next) => {
    userSchema.findById(req.params.id, (error, data) => {
        if (error) {
            return next(error);
        } else {
            res.status(200).json({
                msg: data
            })
        }
    })
})

// Update User
router.route('/update-user/:id').put((req, res, next) => {
    userSchema.findByIdAndUpdate(req.params.id, {
        $set: req.body
    }, (error, data) => {
        if (error) {
            return next(error);
            console.log(error)
        } else {
            res.json(data)
            console.log('User successfully updated!')
        }
    })
})

// Delete User
router.route('/delete-user/:id').delete((req, res, next) => {
    userSchema.findByIdAndRemove(req.params.id, (error, data) => {
        if (error) {
            return next(error);
        } else {
            res.status(200).json({
                msg: data
            })
        }
    })
})

module.exports = router;
Node Server Configuration

Create a server.js file in the token-based authentication project’s folder and paste the following code in it.

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const bodyParser = require('body-parser');
const dbConfig = require('./database/db');

// Express APIs
const api = require('./routes/auth.routes');

// MongoDB conection
mongoose.Promise = global.Promise;
mongoose.connect(dbConfig.db, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then(() => {
    console.log('Database connected')
},
    error => {
        console.log("Database can't be connected: " + error)
    }
)

// Remvoe MongoDB warning error
mongoose.set('useCreateIndex', true);

// Express settings
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));
app.use(cors());

// Serve static resources
app.use('/public', express.static('public'));

app.use('/api', api)

// Define PORT
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
    console.log('Connected to port ' + port)
})

// Express error handling
app.use((req, res, next) => {
    setImmediate(() => {
        next(new Error('Something went wrong'));
    });
});

app.use(function (err, req, res, next) {
    console.error(err.message);
    if (!err.statusCode) err.statusCode = 500;
    res.status(err.statusCode).send(err.message);
});

In this file we defined mongoDB database, express routes, PORT and errors.

Start Node Server

Now, we have placed everything at its place, and now it’s time to start the Node server. Open the terminal and run the given below commands to start the Node server and mongoDB:

Start the MongoDB database:

mongod

Start the nodemon server:

nodemon

You can test Node server on the following URL:
http://localhost:4000/api

Here, are the user authentication CRUD REST APIs built with Node.js.

API Methods API URL
GET (Users List) /api
POST (Sign in) /api/signin
POST (Sign up) /api/register-user
GET (User Profile) /api/user-profile/id
PUT (Update User) /api/update-user/id
DELETE (Delete User) /api/delete-user/id

Conclusion

Finally, we have completed secure Token-Based Authentication REST API with Node.js tutorial. So far, In this tutorial we have learned how to securely store the password in the database using the hash method with bcryptjs, how to create JWT token to communicate with the client and a server using jsonwebtoken. We also implemented the Express input validation using the express-validator plugin.

I hope you liked this tutorial, please share it with others, thanks for reading!