Node.js + MongoDB: User Authentication & Authorization with JWT

In this tutorial, we’re gonna build a Node.js & MongoDB example that supports User Authentication (Registation, Login) & Authorization with JSONWebToken (JWT). You’ll know:

  • Appropriate Flow for User Signup & User Login with JWT Authentication
  • Node.js Express Architecture with CORS, Authenticaton & Authorization middlewares, Mongoose ODM
  • Way to configure Express routes to work with JWT
  • How to define Mongoose Models for Authentication and Authorization
  • How to use Mongoose to interact with MongoDB Database

Related Posts:
Node.js, Express & MongoDb: Build a CRUD Rest Api example
MongoDB One-to-Many Relationship tutorial with Mongoose examples
MongoDB Many-to-Many Relationship with Mongoose examples


Front-end that works well with this:
Angular 8 JWT Authentication with HttpInterceptor and Router
Vue.js JWT Authentication with Vuex and Vue Router
React JWT Authentication (without Redux) example

Token Based Authentication

Comparing with Session-based Authentication that need to store Session on Cookie, the big advantage of Token-based Authentication is that we store the JSON Web Token (JWT) on Client side: Local Storage for Browser, Keychain for IOS and SharedPreferences for Android… So we don’t need to build another backend project that supports Native Apps or an additional Authentication module for Native App users.

in-depth-introduction-jwt-token-based-authentication

There are three important parts of a JWT: Header, Payload, Signature. Together they are combined to a standard structure: header.payload.signature.

The Client typically attaches JWT in Authorization header with Bearer prefix:

Authorization: Bearer [header].[payload].[signature]

Or only in x-access-token header:

x-access-token: [header].[payload].[signature]

For more details, you can visit:
In-depth Introduction to JWT-JSON Web Token

Node.js & MongoDB User Authentication example

We will build a Node.js Express application in that:

  • User can signup new account, or login with username & password.
  • By role (admin, moderator, user), the User has access to protected resources or not

These are APIs that we need to provide:

MethodsUrlsActions
POST/api/auth/signupsignup new account
POST/api/auth/signinlogin an account
GET/api/test/allretrieve public content
GET/api/test/useraccess User’s content
GET/api/test/modaccess Moderator’s content
GET/api/test/adminaccess Admin’s content

Flow for Signup & Login with JWT Authentication

Following diagram shows you the flow that we’re gonna implement for User Registration, User Login and Authorization process.

node-js-mongodb-jwt-authentication-flow

A legal JWT must be added to HTTP x-access-token Header if Client accesses protected resources.

Node.js Express Architecture with Authentication & Authorization

Here is an overview of our Node.js Express App:

node-js-mongodb-jwt-authentication-architecture

Via Express routes, HTTP request that matches a route will be checked by CORS Middleware before coming to Security layer.

Security layer includes:

  • JWT Authentication Middleware: verify SignUp, verify token
  • Authorization Middleware: check User’s roles with record in database

An error message will be sent as HTTP response to Client when the middlewares throw any error, .

Controllers interact with MongoDB Database via Mongoose library and send HTTP response (token, user information, data based on roles…) to Client.

Technology

  • Express 4.17.1
  • bcryptjs 2.4.3
  • jsonwebtoken 8.5.1
  • mongoose 5.9.1
  • MongoDB

Project Structure

This is directory structure for our Node.js Express & MongoDB application:

node-js-mongodb-jwt-authentication-project-structure

Create Node.js App

Create a folder for our project with command:

$ mkdir node-js-jwt-auth-mongodb
$ cd node-js-jwt-auth-mongodb

Then we initialize the Node.js App with a package.json file:

npm init

name: (node-js-jwt-auth-mongodb) 
version: (1.0.0) 
description: Node.js + MongoDB: JWT Authentication & Authorization
entry point: (index.js) server.js
test command: 
git repository: 
keywords: node.js, express, jwt, authentication, mongodb
author: bezkoder
license: (ISC)

Is this ok? (yes) yes

Let’s install necessary modules such as: express, cors, body-parser, mongoose, jsonwebtoken and bcryptjs.
Run the command:

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

Check package.json file, you can see it looks like this:

{
  "name": "node-js-jwt-auth-mongodb",
  "version": "1.0.0",
  "description": "Node.js + MongoDB: JWT Authentication & Authorization",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "node.js",
    "express",
    "jwt",
    "authentication",
    "mongodb"
  ],
  "author": "bezkoder",
  "license": "ISC",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^5.9.1"
  }
}

Setup Express web server

In the root folder, let’s create a new server.js file:

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

const app = express();

var corsOptions = {
  origin: "http://localhost:8081"
};

app.use(cors(corsOptions));

// parse requests of content-type - application/json
app.use(bodyParser.json());

// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));

// simple route
app.get("/", (req, res) => {
  res.json({ message: "Welcome to bezkoder application." });
});

// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}.`);
});

What we’be just done in the code above:
– import express, body-parser and cors modules:

  • Express is for building the Rest apis
  • body-parser helps to parse the request and create the req.body object
  • cors provides Express middleware to enable CORS

– create an Express app, then add body-parser and cors middlewares using app.use() method. Notice that we set origin: http://localhost:8081.
– define a GET route which is simple for test.
– listen on port 8080 for incoming requests.

Now let’s run the app with command: node server.js.
Open your browser with url http://localhost:8080/, you will see:

node-js-mongodb-jwt-authentication-example-setup-server

Configure MongoDB database

In the app folder, create config folder for configuration.

Then create a new db.config.js file that contains parameters for setting up MongoDB later:

module.exports = {
  HOST: "localhost",
  PORT: 27017,
  DB: "bezkoder_db"
};

Define the Mongoose Model

In models folder, create User and Role data model as following code:

models/role.model.js

const mongoose = require("mongoose");

const Role = mongoose.model(
  "Role",
  new mongoose.Schema({
    name: String
  })
);

module.exports = Role;

models/user.model.js

const mongoose = require("mongoose");

const User = mongoose.model(
  "User",
  new mongoose.Schema({
    username: String,
    email: String,
    password: String,
    roles: [
      {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Role"
      }
    ]
  })
);

module.exports = User;

These Mongoose Models represents users & roles collections in MongoDB database.
User object will have a roles array that contains ids in roles collection as reference.

This kind is called Reference Data Models or Normalization. You can find more details at:
MongoDB One-to-Many Relationship tutorial with Mongoose examples

After initializing Mongoose, we don’t need to write CRUD functions because Mongoose supports all of them:

  • create a new User: object.save()
  • find a User by id: User.findById(id)
  • find User by email: User.findOne({ email: … })
  • find User by username: User.findOne({ username: … })
  • find all Roles which name in given roles array: Role.find({ name: { $in: roles } })

These functions will be used in our Controllers and Middlewares.

Initialize Mongoose

Now create app/models/index.js with content like this:

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

const db = {};

db.mongoose = mongoose;

db.user = require("./user.model");
db.role = require("./role.model");

db.ROLES = ["user", "admin", "moderator"];

module.exports = db;

Open server.js and add following code to open Mongoose connection to MongoDB database:

...
const app = express();
app.use(...);

const db = require("./app/models");
const Role = db.role;

db.mongoose
  .connect(`mongodb://${dbConfig.HOST}:${dbConfig.PORT}/${dbConfig.DB}`, {
    useNewUrlParser: true,
    useUnifiedTopology: true
  })
  .then(() => {
    console.log("Successfully connect to MongoDB.");
    initial();
  })
  .catch(err => {
    console.error("Connection error", err);
    process.exit();
  });

...
function initial() {
  Role.estimatedDocumentCount((err, count) => {
    if (!err && count === 0) {
      new Role({
        name: "user"
      }).save(err => {
        if (err) {
          console.log("error", err);
        }

        console.log("added 'user' to roles collection");
      });

      new Role({
        name: "moderator"
      }).save(err => {
        if (err) {
          console.log("error", err);
        }

        console.log("added 'moderator' to roles collection");
      });

      new Role({
        name: "admin"
      }).save(err => {
        if (err) {
          console.log("error", err);
        }

        console.log("added 'admin' to roles collection");
      });
    }
  });
}

initial() function helps us to create 3 important rows in roles collection.

Configure Auth Key

jsonwebtoken functions such as verify() or sign() use algorithm that needs a secret key (as String) to encode and decode token.

In the app/config folder, create auth.config.js file with following code:

module.exports = {
  secret: "bezkoder-secret-key"
};

You can create your own secret String.

Create Middleware functions

To verify a Signup action, we need 2 functions:
– check duplications for username and email
– check if roles in the request is legal or not

middlewares/verifySignUp.js

const db = require("../models");
const ROLES = db.ROLES;
const User = db.user;

checkDuplicateUsernameOrEmail = (req, res, next) => {
  // Username
  User.findOne({
    username: req.body.username
  }).exec((err, user) => {
    if (err) {
      res.status(500).send({ message: err });
      return;
    }

    if (user) {
      res.status(400).send({ message: "Failed! Username is already in use!" });
      return;
    }

    // Email
    User.findOne({
      email: req.body.email
    }).exec((err, user) => {
      if (err) {
        res.status(500).send({ message: err });
        return;
      }

      if (user) {
        res.status(400).send({ message: "Failed! Email is already in use!" });
        return;
      }

      next();
    });
  });
};

checkRolesExisted = (req, res, next) => {
  if (req.body.roles) {
    for (let i = 0; i < req.body.roles.length; i++) {
      if (!ROLES.includes(req.body.roles[i])) {
        res.status(400).send({
          message: `Failed! Role ${req.body.roles[i]} does not exist!`
        });
        return;
      }
    }
  }

  next();
};

const verifySignUp = {
  checkDuplicateUsernameOrEmail,
  checkRolesExisted
};

module.exports = verifySignUp;

To process Authentication & Authorization, we create following functions:
- check if token is provided, legal or not. We get token from x-access-token of HTTP headers, then use jsonwebtoken's verify() function
- check if roles of the user contains required role or not

middlewares/authJwt.js

const jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
const db = require("../models");
const User = db.user;
const Role = db.role;

verifyToken = (req, res, next) => {
  let token = req.headers["x-access-token"];

  if (!token) {
    return res.status(403).send({ message: "No token provided!" });
  }

  jwt.verify(token, config.secret, (err, decoded) => {
    if (err) {
      return res.status(401).send({ message: "Unauthorized!" });
    }
    req.userId = decoded.id;
    next();
  });
};

isAdmin = (req, res, next) => {
  User.findById(req.userId).exec((err, user) => {
    if (err) {
      res.status(500).send({ message: err });
      return;
    }

    Role.find(
      {
        _id: { $in: user.roles }
      },
      (err, roles) => {
        if (err) {
          res.status(500).send({ message: err });
          return;
        }

        for (let i = 0; i < roles.length; i++) {
          if (roles[i].name === "admin") {
            next();
            return;
          }
        }

        res.status(403).send({ message: "Require Admin Role!" });
        return;
      }
    );
  });
};

isModerator = (req, res, next) => {
  User.findById(req.userId).exec((err, user) => {
    if (err) {
      res.status(500).send({ message: err });
      return;
    }

    Role.find(
      {
        _id: { $in: user.roles }
      },
      (err, roles) => {
        if (err) {
          res.status(500).send({ message: err });
          return;
        }

        for (let i = 0; i < roles.length; i++) {
          if (roles[i].name === "moderator") {
            next();
            return;
          }
        }

        res.status(403).send({ message: "Require Moderator Role!" });
        return;
      }
    );
  });
};

const authJwt = {
  verifyToken,
  isAdmin,
  isModerator
};
module.exports = authJwt;

middlewares/index.js

const authJwt = require("./authJwt");
const verifySignUp = require("./verifySignUp");

module.exports = {
  authJwt,
  verifySignUp
};

Create Controllers

Controller for Authentication

There are 2 main functions for Authentication:
- signup: create new User in database (role is user if not specifying role)
- signin:

  • find username of the request in database, if it exists
  • compare password with password in database using bcrypt, if it is correct
  • generate a token using jsonwebtoken
  • return user information & access Token

controllers/auth.controller.js

const config = require("../config/auth.config");
const db = require("../models");
const User = db.user;
const Role = db.role;

var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");

exports.signup = (req, res) => {
  const user = new User({
    username: req.body.username,
    email: req.body.email,
    password: bcrypt.hashSync(req.body.password, 8)
  });

  user.save((err, user) => {
    if (err) {
      res.status(500).send({ message: err });
      return;
    }

    if (req.body.roles) {
      Role.find(
        {
          name: { $in: req.body.roles }
        },
        (err, roles) => {
          if (err) {
            res.status(500).send({ message: err });
            return;
          }

          user.roles = roles.map(role => role._id);
          user.save(err => {
            if (err) {
              res.status(500).send({ message: err });
              return;
            }

            res.send({ message: "User was registered successfully!" });
          });
        }
      );
    } else {
      Role.findOne({ name: "user" }, (err, role) => {
        if (err) {
          res.status(500).send({ message: err });
          return;
        }

        user.roles = [role._id];
        user.save(err => {
          if (err) {
            res.status(500).send({ message: err });
            return;
          }

          res.send({ message: "User was registered successfully!" });
        });
      });
    }
  });
};

exports.signin = (req, res) => {
  User.findOne({
    username: req.body.username
  })
    .populate("roles", "-__v")
    .exec((err, user) => {
      if (err) {
        res.status(500).send({ message: err });
        return;
      }

      if (!user) {
        return res.status(404).send({ message: "User Not found." });
      }

      var passwordIsValid = bcrypt.compareSync(
        req.body.password,
        user.password
      );

      if (!passwordIsValid) {
        return res.status(401).send({
          accessToken: null,
          message: "Invalid Password!"
        });
      }

      var token = jwt.sign({ id: user.id }, config.secret, {
        expiresIn: 86400 // 24 hours
      });

      var authorities = [];

      for (let i = 0; i < user.roles.length; i++) {
        authorities.push("ROLE_" + user.roles[i].name.toUpperCase());
      }
      res.status(200).send({
        id: user._id,
        username: user.username,
        email: user.email,
        roles: authorities,
        accessToken: token
      });
    });
};

Controller for testing Authorization

There are 4 functions:
/api/test/all for public access
/api/test/user for loggedin users (any role)
/api/test/mod for moderator users
/api/test/admin for admin users

controllers/user.controller.js

exports.allAccess = (req, res) => {
  res.status(200).send("Public Content.");
};

exports.userBoard = (req, res) => {
  res.status(200).send("User Content.");
};

exports.adminBoard = (req, res) => {
  res.status(200).send("Admin Content.");
};

exports.moderatorBoard = (req, res) => {
  res.status(200).send("Moderator Content.");
};

Let's combine middlewares with controller functions in the next section.

Define Routes

When a client sends request for an endpoint using HTTP request (GET, POST, PUT, DELETE), we need to determine how the server will response by setting up the routes.

We can separate our routes into 2 part: for Authentication and for Authorization (accessing protected resources).

Authentication:

  • POST /api/auth/signup
  • POST /api/auth/signin

routes/auth.routes.js

const { verifySignUp } = require("../middlewares");
const controller = require("../controllers/auth.controller");

module.exports = function(app) {
  app.use(function(req, res, next) {
    res.header(
      "Access-Control-Allow-Headers",
      "x-access-token, Origin, Content-Type, Accept"
    );
    next();
  });

  app.post(
    "/api/auth/signup",
    [
      verifySignUp.checkDuplicateUsernameOrEmail,
      verifySignUp.checkRolesExisted
    ],
    controller.signup
  );

  app.post("/api/auth/signin", controller.signin);
};

Authorization:

  • GET /api/test/all
  • GET /api/test/user for loggedin users (user/moderator/admin)
  • GET /api/test/mod for moderator
  • GET /api/test/admin for admin

routes/user.routes.js

const { authJwt } = require("../middlewares");
const controller = require("../controllers/user.controller");

module.exports = function(app) {
  app.use(function(req, res, next) {
    res.header(
      "Access-Control-Allow-Headers",
      "x-access-token, Origin, Content-Type, Accept"
    );
    next();
  });

  app.get("/api/test/all", controller.allAccess);

  app.get("/api/test/user", [authJwt.verifyToken], controller.userBoard);

  app.get(
    "/api/test/mod",
    [authJwt.verifyToken, authJwt.isModerator],
    controller.moderatorBoard
  );

  app.get(
    "/api/test/admin",
    [authJwt.verifyToken, authJwt.isAdmin],
    controller.adminBoard
  );
};

Don't forget to add these routes in server.js:

...
// routes
require('./app/routes/auth.routes')(app);
require('./app/routes/user.routes')(app);

// set port, listen for requests
...

Run & Test with Results

Run Node.js application with command: node server.js.

The console shows:

Server is running on port 8080.
Successfully connect to MongoDB.
added 'user' to roles collection
added 'admin' to roles collection    
added 'moderator' to roles collection

Let's check roles collection in MongoDB database:

node-js-mongodb-jwt-authentication-roles-collection

Register some users with /signup API:

  • admin with admin role
  • modera with moderator and user roles
  • bezkoder with user role

node-js-mongodb-jwt-authentication-example-users-registration

users collection after signup could look like this.

node-js-mongodb-jwt-authentication-example-users-collection

Access public resource: GET /api/test/all

node-js-mongodb-jwt-authentication-example-public-resourses

Access protected resource: GET /api/test/user

node-js-mongodb-jwt-authentication-example-protected-resourses

Login an account (with wrong password): POST /api/auth/signin

node-js-mongodb-jwt-authentication-example-login-wrong-password

Login an legal account: POST /api/auth/signin

node-js-mongodb-jwt-authentication-example-login-successful

Access protected resources: GET /api/test/user

node-js-mongodb-jwt-authentication-example-access-resourses

GET /api/test/admin

node-js-mongodb-jwt-authentication-example-access-admin

If we use a wrong access token:

node-js-mongodb-jwt-authentication-example-wrong-token

Conclusion

Oh yeah! Today we've learned so many interesting things about Node.js MongoDB User Authentication with JWT (JSONWebToken) in just a Node.js Express Rest Api example. You also know way to implement role-based Authorization to restrict access to protected resources.

If you need a working front-end for this back-end, you can find Client App in the post:
- Vue.js JWT Authentication with Vuex and Vue Router
- Angular 8 JWT Authentication with HttpInterceptor and Router
- Angular 10 JWT Authentication example with Web Api
- React JWT Authentication (without Redux) example

Happy learning! See you again.

Further Reading

Source Code

You can find the complete source code for this tutorial on Github.

31 thoughts to “Node.js + MongoDB: User Authentication & Authorization with JWT”

  1. Hello, thanks for your work on the guide…
    Having an issue connecting to mongoDB, fixed the connection by adding:
    const dbConfig = require(“./config/db.config”); to server JS – the ${dbConfig.HOST} variables can be found…

    but cant figure were the function inital()… code is placed? the connection just hangs.

    Warm Regards

    1. Right, fully following the steps, const dbConfig = require (“./config/db.config”); line is missing in Initialize Mongoose section.

  2. Hello, thank for the great guide – I have followed it closely, had a few issues…
    Minor:
    1. In the your project structure, you defined the folder “middleware” – but in the guide is referred to as “middlewares”
    2. Initalize Mongoose – adding to the server.js file the db configurations were not found – I added:
    const dbConfig = require(“./config/db.config”);
    just above the mongoose config – worked!

    Having a major issue, when starting up the app and using Postman to register a new user, get the following error serverside:
    TypeError: Cannot read property ‘findOne’ of undefined

    Double check the code and tried looking on-line, couldn’t find anything solid to go on – thought the feedback may help. Thank you

    1. Hey check your

      auth.controller.js and index.js to make sure you have correct values there…

      I had db.users = require(“./user.model.js”)(mongoose); in index.js and const User = db.user; in the controller.

      Please notice the typo there…

  3. Hey thank you, everything worked perfectly the first time! 😀

    FYI – I’m on Windows, and I have previously been instructed to use bcryptjs, but fyi, plain old bcrypt works just fine. I already had bcrypt installed, so instead of also installing bcryptjs, I decided to just try and see if it works, and it did!

    I truly appreciate when I come across a well-written article from someone who actually has working code lol… It’s frustrating how many people write articles and clearly did not even use their own code… grr… so, thanks again!

  4. HI,

    I got this error when model creation, exactly got this one in this line db.user = require(“./user.model”);
    message: ‘Cannot overwrite `users` model once compiled.’,
    name: ‘OverwriteModelError’. how to reproduce this one.

  5. Great tutorial!
    This is something I was looking for.

    You could mention in your other tutorials, this could be used as small reference for a one-to-many for NodeJS – Express – MongoDB

  6. Great tutorial

    i got this error “TypeError: Cannot read property ‘username’ of undefined
    at checkDuplicateUsernameOrEmail” can anyone please help?

    1. you must move these lines
      // routes
      require(‘./routes/auth.routes’)(app);
      require(‘./routes/user.routes’)(app);
      after these lines:
      app.get(“/”, (req, res) => {
      res.json({ message: “Welcome to bezkoder application.” });
      });

      in server.js file.

    2. I was having the same issue. I’m not sure why, but node was having an issue with the import of that verifySignup module. I had to change my import to explicitly be:

      const verifySignup = require(‘../middleware/verifySignUp.js’)

      rather than trying to use the neater importing/object destructuring used in the tutorial.

  7. Hello there,
    I got a problem with the initial() function, result is “Role.estimatedDocumentCount is not a function”
    I’m using mongoDB on cloud Atlas and mongoose version is 5.9.19,
    Thank you for debug information, I really want to practice more this wonderful tutorial 😉
    Cheers.

    1. Role.estimatedDocumentCount is not a function” I got this issue due to old version of mongoose
      used Role.collection.estimatedDocumentCount to solve this.

  8. got this error “TypeError: Cannot read property ‘username’ of undefined
    at checkDuplicateUsernameOrEmail” can anyone please help?

    Same is here also in postman I have set ‘Content-Type’: ‘application/json’ in the HTTP request header. inspite of that I am getting this error please helpme.

  9. Hello Bezkoder,
    how I can redirect to the appropriate page after successful login depending on the Role (user, moderator or admin)?

  10. Hi, loved the post I was wondering if you had any insides on how you would go about unit testing your middleware classes I was looking at verifySignUp, and haven’t been able to figure out how to mock the DB in order to isolate any of the methods for unit testing.

    Thanks a lot for your post!

  11. how can i change this

    module.exports = {
    HOST: “localhost”,
    PORT: 27017,
    DB: “bezkoder_db”
    };

    to my mongo db cloud url , i am getting an error after changing it to this
    module.exports = {
    url: “mongodb+srv://james:success@main.egoxz.azure.mongodb.net/crud?retryWrites=true&w=majority”
    };

    the error i got is this
    throw new MongooseError(‘The `uri` parameter to `openUri()` must be a ‘ +
    ^

    MongooseError: The `uri` parameter to `openUri()` must be a string, got “undefined”. Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.
    at NativeConnection.Connection.openUri (C:\Users\user\Documents\node-js-jwt-auth-mongodb-master\node_modules\mongoose\lib\connection.js:582:11)
    at Mongoose.connect (C:\Users\user\Documents\node-js-jwt-auth-mongodb-master\node_modules\mongoose\lib\index.js:335:15)
    at Object. (C:\Users\user\Documents\node-js-jwt-auth-mongodb-master\server.js:24:2)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47

  12. Great tutorial and great tutorial site!
    I found a weird bug though, might be caused by newer versions installed here.
    auth.controller.signup: Role.Find({ name: {$in: req.body.roles} is case sensitive and matches what is stored in db.
    verifySignup.checkRoleexisted: if(!ROLES.includes(req.body.roles[i]) is also case sensitive and require lowercase because the ROLES are returned as lowercase.
    I solved it by changing to “if(!ROLES.includes(req.body.roles[i].toLowerCase()))” but it is not beautiful in any way.

  13. I am getting this error in my postman “Client network socket disconnected before secure TLS connection was established” what can I do, please help

  14. Hi, great article I must say. Think it’s clicked now how JWT and Express.js working so thank you very much!
    All is working great, already building onto the system.
    Just wondering, what would be the best way to logout the user, reset the password, forgot password? Any tips, please?
    Keep up the good work

  15. I have a question – you have an array of functions being passed to an express route. I wasn’t aware you could do this – and my version of express only allows a single function (not an array). Do you have documentation on how this will execute?

Leave a Reply

Your email address will not be published. Required fields are marked *