Node JS Login and Registration System With Express JS and MySQL

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 *