NodeJS and MongoDB application authentication by JWT

In this blog, we’ll be implementing authentication with JWT in a NodeJS web application. For this, we’ll be using jsonwebtoken package What is JWT? JWT(JSON…

In this blog, we’ll be implementing authentication with JWT in a NodeJS web application. For this, we’ll be using jsonwebtoken package

What is JWT?

JWT(JSON Web Token) is a token format. It is digitally-signed, self-contained, and compact. It provides a convenient mechanism for transferring data. JWT is not inherently secure, but the use of JWT can ensure the authenticity of the message so long as the signature is verified and the integrity of the payload can be guaranteed. JWT is often used for stateless authentication in simple use cases involving non-complex systems.

Here's an example of JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im9sYXR1bmRlZ2FydWJhQGdtYWlsLmNvbSIsIm

Now, let's authenticate/protect some routes.

Pre-requisites:

  • Basic knowledge of HTML/JavaScript
  • NodeJS should be installed in your system.
  • express module for creating the server.
  • mongoose module for MongoDB connection and queries.
  • bcrypt module for hashing.

you can install all required packages by using following command:

npm install express mongoose bcrypt  --save

Step 1. First, create a directory structure as below :

JWTApp

-api
--models
----userModel.js
--controllers
----userController.js
--route
----userRoute.js
--server.js

Step 2. Install “jsonwebtoken” packageby using following command

 npm install jsonwebtoken -- save

Step 3. Create the user model

In the api/models folder, create a file called user userModel.js by running touch api/models/userModel.js.

In this file, create a mongoose schema with the following properties:

  • fullName
  • email address
  • password
  • the created date

Add the following code

'use strict';

var mongoose = require('mongoose'),
  bcrypt = require('bcrypt'),
  Schema = mongoose.Schema;

/**
 * User Schema
 */
var UserSchema = new Schema({
  fullName: {
    type: String,
    trim: true,
    required: true
  },
  email: {
    type: String,
    unique: true,
    lowercase: true,
    trim: true,
    required: true
  },
  hash_password: {
    type: String
  },
  created: {
    type: Date,
    default: Date.now
  }
});

UserSchema.methods.comparePassword = function(password) {
  return bcrypt.compareSync(password, this.hash_password);
};

mongoose.model('User', UserSchema);

Step 4. Create the user handlers

In the api/controllers folder, create a file called user userController.js by running touch api/controllers/userController.js

In the userController file, create three different handlers to handle by using the following code

'use strict';

var mongoose = require('mongoose'),
  jwt = require('jsonwebtoken'),
  bcrypt = require('bcrypt'),
  User = mongoose.model('User');

exports.register = function(req, res) {
  var newUser = new User(req.body);
  newUser.hash_password = bcrypt.hashSync(req.body.password, 10);
  newUser.save(function(err, user) {
    if (err) {
      return res.status(400).send({
        message: err
      });
    } else {
      user.hash_password = undefined;
      return res.json(user);
    }
  });
};

exports.sign_in = function(req, res) {
  User.findOne({
    email: req.body.email
  }, function(err, user) {
    if (err) throw err;
    if (!user || !user.comparePassword(req.body.password)) {
      return res.status(401).json({ message: 'Authentication failed. Invalid user or password.' });
    }
    return res.json({ token: jwt.sign({ email: user.email, fullName: user.fullName, _id: user._id }, 'RESTFULAPIs') });
  });
};

exports.loginRequired = function(req, res, next) {
  if (req.user) {
    next();
  } else {

    return res.status(401).json({ message: 'Unauthorized user!!' });
  }
};
exports.profile = function(req, res, next) {
  if (req.user) {
    res.send(req.user);
    next();
  } 
  else {
   return res.status(401).json({ message: 'Invalid token' });
  }
};

Note: A hash password was saved in the database using bcrypt.

Step 6. In the api/route folder, create a file called user userRoute.js and add the following code:

'use strict';
module.exports = function(app) {
    var userHandlers = require('../controllers/userController.js');
    // todoList Routes
    app.route('/tasks')
        .post(userHandlers.loginRequired, userHandlers.profile);
    app.route('/auth/register')
        .post(userHandlers.register);
   app.route('/auth/sign_in')
        .post(userHandlers.sign_in);
};

Step 7. Add the following code in server.js

'use strict';

var express = require('express'),
  app = express(),
  port = process.env.PORT || 3000,


  User = require('./api/models/userModel'),
  bodyParser = require('body-parser'),
  jsonwebtoken = require("jsonwebtoken");

const mongoose = require('mongoose');
const option = {
    socketTimeoutMS: 30000,
    keepAlive: true,
    reconnectTries: 30000
};

const mongoURI = process.env.MONGODB_URI;
mongoose.connect('mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb', option).then(function(){
    //connected successfully
}, function(err) {
    //err handle
});

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

app.use(function(req, res, next) {
  if (req.headers && req.headers.authorization && req.headers.authorization.split(' ')[0] === 'JWT') {
    jsonwebtoken.verify(req.headers.authorization.split(' ')[1], 'RESTFULAPIs', function(err, decode) {
      if (err) req.user = undefined;
      req.user = decode;
      next();
    });
  } else {
    req.user = undefined;
    next();
  }
});
var routes = require('./api/routes/userRoutes');
routes(app);

app.use(function(req, res) {
  res.status(404).send({ url: req.originalUrl + ' not found' })
});

app.listen(port);

console.log(' RESTful API server started on: ' + port);

module.exports = app;

Step 9. Now you just need to run the project by using the following command and try logging by using the JWT.

npm start

Step 10. Open Postman and create a post request to localhost:3000/auth/register as below:

Postman register

Step 11. After this, let’s sign with this URL localhost:3000/auth/sign_in . Enter the keys and values for email and password

Postman signin

Under the value, add JWT and the token with a space between, like so:

JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im9sYXR1bmRlZ2FydWJhQGdtYWlsLmNvbSIsImZ1bGxOYW1lIjoiT2xhdHVuZGUgR2FydWJhIiwiX2lkIjoiNThmMjYzNDdiMTY1YzUxODM1NDMxYTNkIiwiaWF0IjoxNDkyMjgwMTk4fQ.VcMpybz08cB5PsrMSr25En4_EwCGWZVFgciO4M-3ENE

Step 11. Then, enter the parameters for the key and value for fetching the profile. You want to create as shown below and send:

Postman signin

As we have seen it is fairly easy to build a JWT authentication system with NodeJS, You can found the complete code used in this tutorial here.

Note : You can decode or verify your JWT token details with this tool

Ashish Sharma

Written by Ashish Sharma

Ashish is a software engineer who continually seeks clean, elegant solutions to business challenges. His lifelong passion for technology drives him to proactively expand horizons, constantly exploring and evaluating new languages, platforms, frameworks and tools.

LoginRadius CIAM Platform

Our Product Experts will show you the power of the LoginRadius CIAM platform, discuss use-cases, and prove out ROI for your business.

Book A Demo Today