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 & MongoDB: JWT Refresh Token example
– MERN stack Authentication example
– MEAN stack Authentication with Angular 8 example
– MEAN stack Authentication with Angular 10 example
– MEAN stack Authentication with Angular 11 example
– MEAN stack Authentication with Angular 12 example
– MEAN stack Authentication with Angular 13 example
– MEAN stack Authentication with Angular 14 example
– 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
Deployment: Docker Compose: Node.js Express and MongoDB example
Front-end that works well with this:
– Vue.js JWT Authentication with Vuex and Vue Router
– Angular 8 JWT Authentication example with Web Api
– Angular 10 JWT Authentication example with Web Api
– Angular 11 JWT Authentication example with Web Api
– Angular 12 JWT Authentication example with Web Api
– Angular 13 JWT Authentication example with Web Api
– React JWT Authentication (without Redux) example
– React Hooks: JWT Authentication (without Redux) example
– React Redux: JWT Authentication example
Contents
- Token Based Authentication
- Node.js & MongoDB User Authentication example
- Flow for Signup & Login with JWT Authentication
- Node.js Express Architecture with Authentication & Authorization
- Technology
- Project Structure
- Create Node.js App
- Setup Express web server
- Configure MongoDB database
- Define the Mongoose Model
- Initialize Mongoose
- Configure Auth Key
- Create Middleware functions
- Create Controllers
- Define Routes
- Run & Test with Results
- Conclusion
- Further Reading
- Source Code
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.
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:
Methods | Urls | Actions |
---|---|---|
POST | /api/auth/signup | signup new account |
POST | /api/auth/signin | login an account |
GET | /api/test/all | retrieve public content |
GET | /api/test/user | access User’s content |
GET | /api/test/mod | access Moderator’s content |
GET | /api/test/admin | access 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.
A legal JWT must be added to HTTP x-access-token Header if Client accesses protected resources.
If you want to use Cookies, kindly visit:
Node.js Express and MongoDB: Login and Registration example
You will need to implement Refresh Token:
More details at: Node.js & MongoDB: JWT Refresh Token example
Node.js Express Architecture with Authentication & Authorization
Here is an overview of our Node.js Express App:
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:
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
, mongoose
, jsonwebtoken
and bcryptjs
.
Run the command:
npm install express mongoose 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",
"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 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(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.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’ve just done in the code above:
– import express
and cors
modules:
- Express is for building the Rest apis
- cors provides Express middleware to enable CORS
– create an Express app, then add request 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:
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
withpassword
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:
Register some users with /signup
API:
- admin with
admin
role - modera with
moderator
anduser
roles - bezkoder with
user
role
users
collection after signup could look like this.
Access public resource: GET /api/test/all
Access protected resource: GET /api/test/user
Login an account (with wrong password): POST /api/auth/signin
Login an legal account: POST /api/auth/signin
Access protected resources: GET /api/test/user
GET /api/test/admin
If we use a wrong access 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.
You should continue to know how to implement Refresh Token:
Node.js & MongoDB: JWT Refresh Token example
If you need a working front-end for this back-end, you can find Client App in the post:
- Vue
- Angular 8 / Angular 10 / Angular 11 / Angular 12 / Angular 13
- React / React Hooks / React + Redux
Fullstack with React.js: MERN stack Authentication example
Happy learning! See you again.
Further Reading
- https://www.npmjs.com/package/express
- http://expressjs.com/en/guide/routing.html
- In-depth Introduction to JWT-JSON Web Token
- https://mongoosejs.com/docs/queries.html
- https://mongoosejs.com/docs/api/model.html
Fullstack:
- MEVN: Vue.js + Node.js + Express + MongoDB example
- MEAN:
- Angular 8 + Node.js + Express + MongoDB example
- Angular 10 + Node.js + Express + MongoDB example
- Angular 11 + Node.js + Express + MongoDB example
- Angular 12 + Node.js + Express + MongoDB example
- Angular 13 + Node.js + Express + MongoDB example
- Angular 14 + Node.js + Express + MongoDB example
- MERN: React + Node.js + Express + MongoDB example
Deployment: Docker Compose: Node.js Express and MongoDB example
Source Code
You can find the complete source code for this tutorial on Github.
Using Cookies: Node.js Express and MongoDB: Login and Registration example
Thank you so much for this article. Well explained.
I got your code running on my MongoDB, but every user I signup for has the same role. How do I assign different roles. You should maybe have it set up so that the first login is for Admin role and have them assign other roles? I see there are 3 roles set up in the DB but from login there is no way to assign a role. Where do we assign -user, moderator or Admin role?
Everything works great so far but when I go to my user page it says “No token provided!” When I sent a get request to postman with the same access token as the user has it returns “User content”. Not sure what could be causing the difference in the browser vs through the Postman API
Hi, if you use browser, maybe you run one of my clients (frontend code).
I think the problem is your HTTP request header. You need to notice to choose Bearer Token or x-access-token on the client side. 🙂
thanks.
One of the best thorough and step by step guide to my most challenging concepts authentication.
It is really nice project.
Thank you for your work.
But I have some errors like this:
ReferenceError: Cannot access ‘app’ before initialization
at Object. (E:\Exercise\node-js-jwt-auth-mongodb\server.js:5:37)
please help me!
Hi. I absolutely love your tutorials. I thought I’d let you know that body-parser has been deprecated. Express has integrated the same things body-parser does.
Hello, what does this line do?
db.ROLES = [“user”, “admin”, “moderator”];
Good day. Wonderful tutorial btw. When i tried signing up using roles “user” and “admin” in an array in the request body I got an error saying Cast to [ObjectId] failed for value \”[ ‘user’, ‘admin’ ]\” (type string) at path \”roles.0\””. I don’t know what’s wrong, every other thing works fine. Thanks in advance
Everything works perfectly, how do i register as admin?
Hi, you can use HTTP Client (Postman for example) to send request with
role
in the body.How do i replace the db.config with my values?
module.exports = {
HOST: ‘localhost’,
PORT: 27017,
DB: ‘bezkoder_db’,
};
What do i replace with this to point to my db? I’ve tried connecting my cluster to this but its showing an error
Error: Illegal arguments: undefined, string at Object.bcrypt.hashSync (/Users/mac/Authentication MongoDb/node-auth/node_modules/bcryptjs/dist/bcrypt.js:189:19) at exports.signup (/Users/mac/Authentication MongoDb/node-auth/app/controllers/auth.controller.js:13:22)
choose body format as JSON
in the db place you have to write ypur own database name
I connected using mongo atlas. I figured it out due your advice…. Thanks
I’ve been working with Mongo atlas starting from scratch, so duplicating someone else code or just utilizing Mongodb is a little tricky to me. Please excuse me for being a noob and explain….
Thanks for replying… Do I have to install locally? I don’t see it under services…
You can find the way to install it on Google.
I copied the github code and can’t get the mongodb connection to work.
Error:
Connection error MongooseServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
Hi, did you start MongoDB on your machine?
Hi, in my case I have to:
install locally: % brew install mongodb/brew/[email protected]
and then: % brew services start [email protected]
Hi man thank you so much for this tutorial.
But i have a problem on “verifySignUp.js” that “username” in the last of this line ‘username: req.body.username’
( TypeError: Cannot read property ‘username’ of undefined:
checkDuplicateUsernameOrEmail (E:\node.js-backend\app\middlewares\verifySignUp.js:10:24))
i don’t know how to fix it please help me
Hi, you can check if your HTTP request header includes Content-Type: application/json.
throw new TypeError(‘app.use() requires a middleware function’)
^
TypeError: app.use() requires a middleware function
at Function.use (/Users/ahmadirshad/Desktop/test/node-js-jwt-auth-mongodb/node_modules/express/lib/application.js:210:11)
at Object. (/Users/ahmadirshad/Desktop/test/node-js-jwt-auth-mongodb/server.js:6:5)
I am getting this error anyone here for help?
Thank you so much for this tutorial….It was very helpful for me…I really appreciate it….could you tell me why did you use next() in verifySignUp.js?
Thank you so much for this tutorial it has been very helpful! Just in case anyone stumbles across any issues setting this up in conjunction with nuxtjs auth, i found adding req.headers.authorization to the authJWT middleware file. “let token = req.headers[“x-access-token”] || req.headers.authorization || req.body.token;”
Thank you for all your effort sharing awesome tutorials here. We really appreciate it.
man you are awesome, very thanks for this tutorials.
THANKS. WONDERFUL TUTORIAL!!
Great tutorial😍😍. Worked perfectly… Thank You, Sir
Hi, can someone elaborate in `.populate(“roles”, “-__v”)`, why we have used `-__v`. You can find the populate function in auth.controllers.js
It means “excluding the __V field(version key) when populate the query”. It is generated whenever a document is inserted by Mongoose.
Hello, I want to display the data of a user in flatlist , but i didn’t find what to modify in routes/controller so i can do this , i’ll appreciate if you can help me
hiii thank you so much for this tutorial but i’m actually facing some problems with the roles as they don’t show in the db when i sign up a new user
hi i keep getting network error when trying to submit a form not sure why no error and all is working fine.
hello, when I do this in my routes :
const { authJwt } = require(“../middlewares”);
const controller = require(“../controllers/user.controller”);
I have the error
/var/www/html/MERN-authentification-with-nodeJS-express-mongo-DB-react-redux/backend/routes/user.routes.js:14
const { authJwt } = require(“../middlewares”);
^^^^^
SyntaxError: Unexpected token ‘const’
Thanks for this amazing post, Initially I faced issue but with going through comments. Everything gone fine. I really appreciate your work. Including this blog I found your another blogs useful too. Thanks mate
Hi,
First of all thanks for the tutorial. At a level of concepts, I got it. At the practical level, User.findOne is not a function hits me from checkDuplicateUsernameOrEmail() in verifySignUp middleware.
What is this error actually telling me? I am understanding this as the seat is taken somehow.
I have googled it for a while but there’s nothing wrong with the syntax from what I can understand. Any solutions or at least a more detailed explanation of why this is occuring?
I have checked that mongoose it’s installed. I manage to connect to the mongo database and inser the roles data, but when I try to add a new user via the api i receive this error
TypeError: User.findOne is not a function
at checkDuplicateUsernameOrEmail (/home/alin/Work/BackEnd/token-based-auth/app/middlewares/verifySignUp.js:7:8)
Thanks.
Best,
Alin
In my user.model.js at the very last line i was exporting module.exports = ‘User’; instead of module.exports = User;
Thanks again!
make me happy after competing this module…that make me feel i am expert with node.js
….thanks a lot..
Good tutorial! Thanks!
Hey there,
I really appreciate your site and the code you’re offering us.
I’m a (backend)beginner and really blown away from the complexity of your code (in a postive way). It seems so clean and well made. My question is… what is your experience and how long did you code? As far as I can understand this code.. this is clean and clear at the same time! My biggest concern right now is,that I cannot write this whole code alone at all. Backend is special for itself. What is your opinion about that? Thanks in advance!
I appreciate, cause I found the tutorial what I was looking for. You’ve ended my four day long hunt! God Bless you man. Have a great day. Thanks!
Hi sir, that a great tutorial! But i have an error at:
TypeError: Role.estimatedDocumentCount is not a function
Why? Thanks
did the x-access-token came as a header or is it typed by copying accessToken and pasting it in headers. plllsssss reply
Muy buen tutorial!!! Gracias
It is giving error for an HTTPS request….working for http. Why?
Great Guide! Just a slight problem on my end with the Bcrypt hashing as it continuously gives me an error that writes : “Error: Illegal arguments: undefined, string at Object.bcrypt.hashSync”. Not sure if this is normal or dependency error, please advice. Thanks in advance!
you need to set the dropdown to JSON in you postman for the body parameter
This was my problem when I couldn’t register a user successfully, thanks!
I´ve the same issue, too.
Have anybody a solution?
okay, i fixed it.
Solution was: a typo
a typo where cause i cant find any in mine
I checked over and over for typos. I had Body -> raw -> JSON selected and still got this error. Finally, I saw comment from Partha above…
“Same is here also in postman I have set ‘Content-Type’: ‘application/json’ in the HTTP request header.”
I put that in the header, and voila! worked.
You need to select Body – > raw -> JSON(application/json)
Thanks,
Netleaf
Really awesome.
Upon downloading the code from your GitHub page the code does not work. I get the error Cannot GET /api/auth/signup. Can you advise how to fix this as I did not modify the code in any way.
Hi, please make sure that your MongoDB runs correctly with db configuration, and the Node.js server runs successfully also.
Hi please make sure you are making a POST request and not a GET requrest
C:\Users\test\Desktop\testing\node-js-jwt-auth-mongodb\server.js:24
.connect(`mongodb://${dbConfig.HOST}:${dbConfig.PORT}/${dbConfig.DB}`, {
^
TypeError: Cannot read property ‘connect’ of undefined
at Object. (C:\Users\test\Desktop\testing\node-js-jwt-auth-mongodb\server.js:24:4)
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
getting an error like this please help.
you can check again module.exports in config file! I think the problem about the syntax :))
you need [const dbConfig = require(“./app/config/db.config.js”);] in server.js
Hello,
I am having a lot of issues with this tutorial and nothing is working for me so far…
I follow the Node.js, Express & MongoDb: Build a CRUD Rest Api example to get a front and back end. I’m basically trying to do this tutorial to get the user to log in to then access all the Tutorials (from the mentioned tutorial). But it wasn’t working. Now I’m simply trying to make this one work on its own and I am getting : TypeError: User.findOne is not a function at checkDuplicateUsername
I am on my mac, using mongo community 4.4. I’m not sure why I am getting this error
Great tutorial. I really enjoyed reading it.
Would be nice to have fully asynchronous functions.
This is awesome. it will be much helpful if you can guide for APIs s in clouddb.
How To Redirect From Backend To Frontend After Authentication ?
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?
Hi, you can find the instruction here:
https://expressjs.com/en/guide/routing.html (Route handlers)
If you have it like me, then the following worked for me because there can be any amount of callback functions sent and I found out that the first callback is executed first:
router.get(‘/test/admin’, authJwt.verifyToken, authJwt.isAdmin, adminBoard)
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
Yeah have the same doubt.
(And same feeling about the article too. Very helpful).
thank you very much
can you help me, How to extract id user I need just id
I am getting this error in my postman “Client network socket disconnected before secure TLS connection was established” what can I do, please help
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.
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:[email protected]/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
James I did like that… in the server.js
I clear:
“db.mongoose
.connect(`mongodb://${dbConfig.HOST}:${dbConfig.PORT}/${dbConfig.DB}`, {
useNewUrlParser: true,
useUnifiedTopology: true
}) ”
and create:
“const path = ‘mongodb+srv://USER:[email protected]/DB?retryWrites=true&w=majority’;
db.mongoose
.connect(path, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true
})”
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!
Hello Bezkoder,
how I can redirect to the appropriate page after successful login depending on the Role (user, moderator or admin)?
Hey jm61 even i want to know this, did you get how to redirect ?
That would be of interest for me, too 🙂
[authJwt.verifyToken, authJwt.isModerator, authJwt.isAdmin]
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.
you probably have your routes set before body-parser parameters
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
use these line of code in server.js file
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.
it’s working now! Great Tutorial thanks
Role.estimatedDocumentCount is not a function” I got this issue due to old version of mongoose
used Role.collection.estimatedDocumentCount to solve this.
Hello how you solve this problem because i have te same problem, Im using MongoDB Atlas v4.8 and i get this error:
Connection error TypeError: Role.estimatedDocumentCount is not a function
Great tutorial
i got this error “TypeError: Cannot read property ‘username’ of undefined
at checkDuplicateUsernameOrEmail” can anyone please help?
Hi, maybe you forgot to set
'Content-Type': 'application/json'
in the HTTP request header.thank you very much for your guide
it will be great help if help me out in solving this prblm
error is:
C:\Users\Lenovo\feb-mern-2020\mern project\node-js-jwt-auth-mongodb\server.js:24
.connect(`mongodb://${dbConfig.HOST}:${dbConfig.PORT}/${dbConfig.DB}`, {
^
TypeError: Cannot read property ‘connect’ of undefined
at Object. (C:\Users\Lenovo\feb-mern-2020\mern project\node-js-jwt-auth-mongodb\server.js:24:4)
at Module._compile (internal/modules/cjs/loader.js:1158:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
at Module.load (internal/modules/cjs/loader.js:1002:32)
at Function.Module._load (internal/modules/cjs/loader.js:901:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
at internal/main/run_main_module.js:18:47
you need [const dbConfig = require(“./app/config/db.config.js”);] in server.js
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.
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.
Check the imports and exports. Do not use const { verifySignUp } = require(“../middlewares”); instead use const verifySignUp = require(“../middlewares”);
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
use these line of code in server.js file
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
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.
Hi, maybe you have instantiated
mongoose.Model()
on the same schema twice.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!
Hi I am getting error as app.use is not a function. Can anyone please help?
Hi, please make sure that you initialize Express correctly.
Great tutorial. Worked perfectly for me…Really helpful man
Nice tutorial!! Really helpful for me.. Thanks a lot!!
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
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…
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
Hi, it is in server.js. You can find where to put it in the tutorial, or source code at Github.
My bad! was chasing a spelling error, doh!
Thanks for the reply 🙂
Right, fully following the steps, const dbConfig = require (“./config/db.config”); line is missing in Initialize Mongoose section.
const dbConfig = require(“./app/config/db.config”);
include this