In this series of tutorials we will develop a complete login, registration and authentication system with Node.js and MongoDB database. We already have a old tutorial published two years back. This will be a updated one with latest code.

Some changes and features when compared to the old one,

-> Use JSON Web Token for session handling.

-> Passwords are hashed using Bcrypt hashing algorithm.

-> Basic Authentication for login authentication.

-> Use ES6 syntax and Promises instead of callbacks.

The ES6 Features we use are,

-> Promises

-> Arrow functions

-> const and let identifiers instead of var

Note :

ES6 is the latest revision of JavaScript which was released in 2015.

Prerequisites

-> Setup Node.js run time and npm in your Operating System (Windows, Linux or OS X). Download Node.js from the link given below.

This is used for login authentication. The email and password is sent by client as a Base64 encoded string in header which is decoded by this module.

bcyptjs

Use to create and verify password hash using bcrpyt hasing algorithm.

body-parser

This is used to parse the JSON body in each request.

express

This is the complete framework used to create RESTful web services.

jsonwebtoken

This is used to create JSON Web Token which is used for session handling.

mongoose

This module is used to connect to MongoDB database.

morgan

This module is used to print logs in terminal for each http request.

nodemailer

This module is used to sent mail using SMTP for forgot password process.

randomstring

This module is used to generate random string which we use as a token for reset password.

Project Structure

The image given below shows the exact project structure.

Creating config.json

Create a new config.json file. This file will be present in config directory. This file has some predefined constants such as email id, password and secret for creating JSON Web Token. The email id and password defined in this file will be used to send mail using SMTP. I have tested with Gmail.

config.json

Creating MongoDB model

Create a user.js file in which we define our MongoDB collection schema. Instead of using var, we are going to use ES6 const and let identifier for assigning variables. The const is immutable where let is mutable also both are block scoped when compared to var.

Creating functions

We have 4 functions files register.js, login.js, profile.js and password.js which has functions defined for the subsequent operation.

The register.js file consists of register function which saves data to MongoDB database. Instead of using the default Javascript callbacks we are using the new ES6 Promises. When creating a Promise we call resolve() for success operation and reject() for failure operation. Similarly when calling a promise then() is called for success and catch() is called for failure. We also replaced function definition with ES6 Arrow functions.

The login function is defined in login.js which authenticates the user and returns a JSON Web Token or else it throws a error.

Similarly profile.js has fucnction which returns users profile.

Finally the password.js file has definition for change password and rest password functionalities. The rest password is a two step process. The first step is to generate a random token and send to user’s email using nodemailer. The second step is to verify the token and change the password to a new one.

Defining routes

All the RESTful endpoints are defined in routes.js file using the new Express 4 router. The default root endpoint returns a welcome message.

The /authenticate endpoint is used for login operation. The POST request in /users endpoint is used to add a new user.

The GET request in /users/email endpoint is used to get the user profile details. The generated JSON Web Token should be present in the header for the field x-access-token.

Similarly PUT operation is used to change the password using old and new password. Also x-access-token should be present in header for this request.

Finally POST request in /users/email/password is used for reset password operation. Sending a empty body will trigger the operation which sends a token in email. This token expires in 2 minutes. Sending body with token and new password resets the password.

The URL will be in the format http://learn2crack/{token}. And we add a intent filter in the Android app, so that whenever this link is clicked it will open our app and we use the token value to reset password.

app.use(‘/api/v1’, router); makes sure each and every endpoint has /api/v1 prefixed to it.

Limyandi Vico Trico

Hey Raj, how can i see the database of the user registered?

Nikola Brodar

In this tutorial Raj Amal, use mongo for database. You see this database in “Robomongo, a GUI client used to create and view databases” or in webStorm, but you need to download plugin there. There are other many IDEA or ways where you can see your database. you can see also your database in some terminal, (for example cmd or git bash terminal)

Nikola Brodar

Please help.. can somebody show me how to create sql query with “like order, statement” in sql.. I know, I need to change this here(user.find({email: email}), but I don’t get it.. new Promise((resolve,reject) => { user.find({email: email})

I don’t know how to do this.. I have tried already for 2 hours without luck.

I have searched on google something like, “mongoose promises similar order to like in sql”

I have solved this problem. I wanted for example if user insert into edittext some text “Ra”, that it prints, show all user that are having in there name “Ra” in textview.. now seever returns to me all wanted users with string “Ra” inside there names.this I have done that I have post request to server, in retrofit 2 I’m using Call(User) getWantedUsers(@Body User user) instead of observle and I needed to create new retrofit builder, change it little bit.. and I needed to create new function in node js and change it little bit.

I have tried this same stuff to do with promisse inside node js and mongo, and it did not worked for me. That way I needed to create function and change it little bit.

Did you try Raj something similar like me, with promisses inside node js? So I want if user insert something inside edittext(for example “Ra”) , that node js returns all users that have “Ra” in there names, and print it to some textview.

Hi there I test my app through postman, and so far register work with the standard Json file. However I can’t login using an Json file, is it could be because the server doesn’t take json file that contain clear text password ? Is there any way to test all the API through postman ? Thank you.

Hi, I have everything working except when I try to reset password it just gives me an Internal Server Error. If I put in an incorrect e-mail it shows that isn’t a valid email, but if I try to put in an e-mail to an existing account it just instantly gives me the Internal Server Error. Is there some variable I need to change that I missed or something? Not sure why this one single thing is being a problem. Thanks

Konidias

Ah nevermind, I just noticed gmail sent a bunch of alerts that a “Less Secure App” attempt to access my mail was blocked. I changed the setting to allow less secure apps access and it worked, but I don’t think this is a good permanent solution… is there a way I can use gmail securely with this app in order to send reset requests? Otherwise I guess I can just use a mail server set up for it?

Ion

Hi, nice article. How can we refresh tokens periodically?

Andrew

Hey man great tutorial. But would you mind if you could explain better the login part? For example I can not understand the users.length == 0 part as well how the user function correlates with the right user in the database in order to extract the right password. I would appreciate if you could explain this part. Thanks

Anubhav Arora

Hey man, users.length == 0 checks if there is any user with the specified email or not, if there is no such user, return result will be 0. Also, while constructing the schema, you can make the email to be unique, so that there will be only one user with a specific email id, in this case you will always get a single return in case of a match and then instead of users[0], you can directly use, the parameter.