Node JS Login and Registration System With Express JS and MySQL

πŸ“† Last updated Jun 23, 2020 πŸ‘· By, Chandan Tudu
Node JS Login and Registration System With Express JS and MySQL Databse

Node JS (Express JS, MySQL) Login and Registration System

Learn how to create a simple Node JS Login and Registration System With Express JS Framework & MySQL Database.

The purpose of this tutorial is to give an idea of creating a Login and Registration system using Node JS.

You should learn first before creating this application –


Follow the below steps to create this Node JS Login Registration System

Step 1: Database Setup

First of all, we have to create our database and database table where we will store user information. In the following, you can see the database information –

  • Database Name – nodejs_login
  • Table name – users

Now open your MySQL DB or MariaDB and create a new database called nodejs_login. And after creating this DB, use the following SQL code to create the `users` table and the structure of the user table –

CREATE TABLE `users` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
 `email` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
 `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Step 2: Node JS env setup & installing node packages

After completing the Database configuration, create a new folder on your Desktop, and name it whatever you want. Here I named it πŸ“nodejs_login.

Now go inside the nodejs_login folder and initialize the NPM with the help of the npm init command.

After that, you have to install some Node Packages to create this application in my way. Use the following command to install those packages –

npm install --save express ejs express-validator cookie-session bcrypt mysql2

After installing the above node packages my package.json file looks like the following –

{
  "name": "nodejs_login",
  "version": "1.0.0",
  "description": "Node JS Login And Registration System",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "w3jar.com",
  "license": "ISC",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "cookie-session": "^1.3.3",
    "ejs": "^2.6.2",
    "express": "^4.17.1",
    "express-validator": "^6.1.1",
    "mysql2": "^1.6.5"
  }
}

Step 3: Creating files & folders

Now time to create the application files & folders. But, before going further, let’s have a look at the nodejs_login folder structure. See the below image –

Node js login Folder Structure
Node js login & Registration App Folder Structure

First, we will create the views, therefore create a new folder inside the nodejs_login folder called πŸ“views.

Inside the views folder, we will create two views –

  • home.ejs – Only logged-in users can access this view.
  • login-register.ejs – Here, a user can log in or sign up.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Home</title>
    <!-- BOOTSTRAP CDN -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
    <div class="container p-5">
        <div class="card">
            <div class="card-body">
                    <h1>Hello, <%= name %></h1>
                    <a href="/logout" class="btn btn-danger">Logout</a>
            </div>
        </div>
    </div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Login Or Register</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
    <div class="container p-5">
        <h1 class="text-center mb-5 text-uppercase text-muted">Node JS Login and Registration System</h1>
        <div class="row">
            <div class="col-sm-5 bg-light border rounded py-3">
                <h2 class="text-center">Login</h2>
                <form action="" method="POST">
                    <div class="form-group">
                      <label for="_email">Email</label>
                      <input type="text" name="user_email" id="_email" class="form-control" placeholder="Email" rnodeequired>
                    </div>
                    <div class="form-group">
                      <label for="_pass">Password</label>
                      <input type="password" name="user_pass" id="_pass" class="form-control" placeholder="Password" required>
                    </div>
                    <% if (locals.login_errors) { 
                      login_errors.forEach(function(error_msg){ %>
                      <div class="alert alert-danger" role="alert"><%= error_msg %></div>
                    <% });
                    } %>
                    <button type="submit" class="btn btn-primary">Login</button>
                </form>
            </div>
            <div class="col-sm-6 bg-light rounded border py-3 offset-sm-1">
                <h2 class="text-center">Register</h2>

                <form action="/register" method="POST" novalidate>
                        <div class="form-group">
                          <label for="_rname">Name</label>
                          <input type="text" name="user_name" id="_rname" class="form-control" placeholder="Name" value="<%= (locals.old_data) ? old_data.user_name : ''; %>" required>
                        </div>
                        <div class="form-group">
                          <label for="_remail">Email</label>
                          <input type="email" name="user_email" id="_remail" class="form-control" placeholder="Email" value="<%= (locals.old_data) ? old_data.user_email : ''; %>" required>
                        </div>
                        <div class="form-group">
                          <label for="_rpass">Password</label>
                          <input type="password" name="user_pass" id="_rpass" class="form-control" placeholder="Password" required>
                        </div>
                        <% if (locals.register_error) { 
                          register_error.forEach(function(error_msg){ %>
                          <div class="alert alert-danger" role="alert"><%= error_msg %></div>
                        <% });
                        } %>
                        <button type="submit" class="btn btn-success">Sign Up</button>
                    </form>

            </div>
        </div>
    </div>
</body>
</html>

After creating the views, Now on the root of the nodejs_login folder, we have to create two files –

  • database.js – This is for making the Database Connection with the MySQL Database.
  • index.js – This is the app root file, here we will perform the login, registration, and logout actions.
const mysql = require('mysql2');
const dbConnection = mysql.createPool({
    host     : 'localhost', // MYSQL HOST NAME
    user     : 'root', // MYSQL USERNAME
    password : '', // MYSQL PASSWORD
    database : 'nodejs_login' // MYSQL DB NAME
}).promise();
module.exports = dbConnection;
const express = require('express');
const path = require('path');
const cookieSession = require('cookie-session');
const bcrypt = require('bcryptjs');
const dbConnection = require('./database');
const { body, validationResult } = require('express-validator');

const app = express();
app.use(express.urlencoded({extended:false}));

// SET OUR VIEWS AND VIEW ENGINE
app.set('views', path.join(__dirname,'views'));
app.set('view engine','ejs');

// APPLY COOKIE SESSION MIDDLEWARE
app.use(cookieSession({
    name: 'session',
    keys: ['key1', 'key2'],
    maxAge:  3600 * 1000 // 1hr
}));

// DECLARING CUSTOM MIDDLEWARE
const ifNotLoggedin = (req, res, next) => {
    if(!req.session.isLoggedIn){
        return res.render('login-register');
    }
    next();
}

const ifLoggedin = (req,res,next) => {
    if(req.session.isLoggedIn){
        return res.redirect('/home');
    }
    next();
}
// END OF CUSTOM MIDDLEWARE

// ROOT PAGE
app.get('/', ifNotLoggedin, (req,res,next) => {
    dbConnection.execute("SELECT `name` FROM `users` WHERE `id`=?",[req.session.userID])
    .then(([rows]) => {
        res.render('home',{
            name:rows[0].name
        });
    });
    
});// END OF ROOT PAGE


// REGISTER PAGE
app.post('/register', ifLoggedin, 
// post data validation(using express-validator)
[
    body('user_email','Invalid email address!').isEmail().custom((value) => {
        return dbConnection.execute('SELECT `email` FROM `users` WHERE `email`=?', [value])
        .then(([rows]) => {
            if(rows.length > 0){
                return Promise.reject('This E-mail already in use!');
            }
            return true;
        });
    }),
    body('user_name','Username is Empty!').trim().not().isEmpty(),
    body('user_pass','The password must be of minimum length 6 characters').trim().isLength({ min: 6 }),
],// end of post data validation
(req,res,next) => {

    const validation_result = validationResult(req);
    const {user_name, user_pass, user_email} = req.body;
    // IF validation_result HAS NO ERROR
    if(validation_result.isEmpty()){
        // password encryption (using bcryptjs)
        bcrypt.hash(user_pass, 12).then((hash_pass) => {
            // INSERTING USER INTO DATABASE
            dbConnection.execute("INSERT INTO `users`(`name`,`email`,`password`) VALUES(?,?,?)",[user_name,user_email, hash_pass])
            .then(result => {
                res.send(`your account has been created successfully, Now you can <a href="/">Login</a>`);
            }).catch(err => {
                // THROW INSERTING USER ERROR'S
                if (err) throw err;
            });
        })
        .catch(err => {
            // THROW HASING ERROR'S
            if (err) throw err;
        })
    }
    else{
        // COLLECT ALL THE VALIDATION ERRORS
        let allErrors = validation_result.errors.map((error) => {
            return error.msg;
        });
        // REDERING login-register PAGE WITH VALIDATION ERRORS
        res.render('login-register',{
            register_error:allErrors,
            old_data:req.body
        });
    }
});// END OF REGISTER PAGE

// LOGIN PAGE
app.post('/', ifLoggedin, [
    body('user_email').custom((value) => {
        return dbConnection.execute('SELECT `email` FROM `users` WHERE `email`=?', [value])
        .then(([rows]) => {
            if(rows.length == 1){
                return true;
                
            }
            return Promise.reject('Invalid Email Address!');
            
        });
    }),
    body('user_pass','Password is empty!').trim().not().isEmpty(),
], (req, res) => {
    const validation_result = validationResult(req);
    const {user_pass, user_email} = req.body;
    if(validation_result.isEmpty()){
        
        dbConnection.execute("SELECT * FROM `users` WHERE `email`=?",[user_email])
        .then(([rows]) => {
            bcrypt.compare(user_pass, rows[0].password).then(compare_result => {
                if(compare_result === true){
                    req.session.isLoggedIn = true;
                    req.session.userID = rows[0].id;

                    res.redirect('/');
                }
                else{
                    res.render('login-register',{
                        login_errors:['Invalid Password!']
                    });
                }
            })
            .catch(err => {
                if (err) throw err;
            });


        }).catch(err => {
            if (err) throw err;
        });
    }
    else{
        let allErrors = validation_result.errors.map((error) => {
            return error.msg;
        });
        // REDERING login-register PAGE WITH LOGIN VALIDATION ERRORS
        res.render('login-register',{
            login_errors:allErrors
        });
    }
});
// END OF LOGIN PAGE

// LOGOUT
app.get('/logout',(req,res)=>{
    //session destroy
    req.session = null;
    res.redirect('/');
});
// END OF LOGOUT

app.use('/', (req,res) => {
    res.status(404).send('<h1>404 Page Not Found!</h1>');
});

app.listen(3000, () => console.log("Server is Running..."));

Completed. Now start your MySQL server and then start your application with the help of the `node index` or `nodemon index` command.

14 Comments

Leave a Reply

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