Node JS Login and Registration System With Express JS and MySQL Databse

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

Here you will learn how to create a simple Node JS Login and Registration System With Express JS & 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 –


To Create this Node JS Login Registration System Follow the below Steps

1 – Step

In the first, we will create our Database and Database table.

Database Name – nodejs_login
Table name – users

After creating the nodejs_login Database, use the following SQL Code for creating 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;

2 – Step

After completing the Database configuration, Now we will create our Node JS Login app.

First, create a new folder on your Desktop, and name it whatever you want. Here I named it nodejs_login.

After that, go inside the folder and initialize NPM (npm init). After Initializing the NPM, Now you need to install some Node Packages.

List of Node Packages:

npm install --save express ejs express-validator cookie-session bcrypt mysql2
{
  "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": {
    "bcrypt": "^3.0.6",
    "cookie-session": "^1.3.3",
    "ejs": "^2.6.2",
    "express": "^4.17.1",
    "express-validator": "^6.1.1",
    "mysql2": "^1.6.5"
  }
}

3 – Step

Creating Files:

Now we will create our app. But, before going further, let’s have a look at the nodejs_login folder structure.

nodejs_login Folder Structure

Node js login Folder Structure

First, we will create our views, for that create a new folder inside the nodejs_login folder and name it views.

Inside the views folder, we need to create two views – home.ejs and login-register.ejs

Only logged-in users can access this home.ejs view.

<!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>

Then we will create the login-register.ejs view in the same folder

<!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 in the root of the nodejs_login folder, we have to create two files – database.js and index.js

We will create the database.js file for making Database Connection with the MySQL Database.

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;

In the end, we will create index.js file

const express = require('express');
const path = require('path');
const cookieSession = require('cookie-session');
const bcrypt = require('bcrypt');
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 bcrypt)
        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 (node index or nodemon index)

Leave a Reply

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