DEV Community

Cover image for [Easy] Complete user Login and Registration using NodeJS, ExpressJs, MySQL and JWT.
Rahul Nikam
Rahul Nikam

Posted on • Updated on

[Easy] Complete user Login and Registration using NodeJS, ExpressJs, MySQL and JWT.

Couple months back I was also searching for the same thing, But unluckily I couldn't find any good resources from YouTube and from Google, But somehow from visiting 10 different website for 10 different things I finally managed to get idea of Login and Registration System in NodeJS and MySQL. The thing to get noticed is you will find many resources of Login and Registration System using NodeJS and MongoDB, but there are very few for MySQL or I'll say few with no sense.

Prerequisites:

You should be knowing basic of JavaScript, HTML, CSS, Bootstrap, NodeJS, Express, MySQL and its fine if you don't know have advance knowledge in this after completely reading this article you will get the complete IDEA.

Installing Dependencies:

Install NodeJS and XAMPP,
NodeJS - Download NodeJs
XAMPP - Download XAMPP

Run the following command in your root directory terminal:
npm install express express-handlebars mysql nodemon bcrypt body-parser cookie-parser dotenv jsonwebtoken

Look at the folder structure!

Folder Structure

Creating Server:

Type the following code in app.js.


const express = require('express');
const app = express();
const port = process.env.PORT || 5000;

app.listen(port, () => {
    console.log('Server Started');
});
Enter fullscreen mode Exit fullscreen mode

This will create a server on Port 5000. Now you can open http://localhost:5000 on your browser but before that, creating server is not only the thing we have to do so let's import all other dependencies and start writing the code.

Creating Database and Table:

Create a database and one table, Table should include field like id, name, email, password and bio. Make sure to crange the name of database and table from the code which I have provided.

Main Code:

In app.js start typing the following code, Check the comments for better understanding.


const express = require('express');
const mysql = require('mysql');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
require('dotenv').config();

const app = express();
const port = process.env.PORT || 5000;

app.use(bodyParser.urlencoded({
    extended: false
}))

// Converting JSON to JavaScript Objects
app.use(bodyParser.json());

// Accessing Cookies from user's Browser
app.use(cookieParser())

// Telling our backend that the static files of our website are going to be in which folder!!
app.use(express.static('public'));

//Template Engines 
app.engine("hbs", exphbs({ extname: '.hbs' }))
app.set('view engine', 'hbs');

// DataBase Credentials
const pool = mysql.createPool({
    connectionLimit: 100,
    host           : 'localhost',
    user           : 'root',
    password       : '',
    database       : 'users',
})

// Connecting to DB
pool.getConnection((err, connection)=>{
    if(err){
        throw err;
    }
    else{
        console.log('Connection Successful and Connected');
    }
});

// All Routers Middleware Setup => 
const homeRoutes = require('./server/routes/homeRoutes');
app.use('/', homeRoutes);

const authRoutes = require('./server/routes/authRoutes');
app.use('/auth', authRoutes);

app.listen(port, () => {
    console.log('Server Started');
});
Enter fullscreen mode Exit fullscreen mode

NOTE : make sure to hide your database credentials in .env file.

Creating Routes:

//type this following code in authRoute.js

const router = require('express').Router();
const { tokenValidation } = require('../../auth/userToken');
const controllers = require('../controllers/authController');

// Routes
// Login
router.get('/login', controllers.ViewLoginPage)
router.post('/login', controllers.Loginuser)

// Register
router.get('/register', controllers.ViewRegisterPage)
router.post('/register', controllers.RegisterNewPage)

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

const router = require('express').Router();
const controllers = require('../controllers/homeController');
const { tokenValidation } = require('../../auth/userToken');

// Routes
router.get('/', controllers.HomePage);
router.get('/user-profile', tokenValidation, controllers.userProfilePage);

//NOTE: dont get confuse with why am i passing to middlewares in route user-profile, once we learn the JWT then you will get this.

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

Creating Controllers for Home and Auth:

//type the following code in authControllers.js


const mysql = require('mysql');
const { hashSync, genSaltSync, compareSync } = require('bcrypt');
const { sign } = require('jsonwebtoken');
require('dotenv').config();

const pool = mysql.createPool({
    connectionLimit: 100,
    host: "localhost",
    user: "root",
    password: "",
    database: "users",
})


exports.ViewLoginPage = (req, res) => {
    res.render('login', { title: 'Login' })
}
exports.ViewRegisterPage = (req, res) => {
    res.render('register', { title: 'Register' })
}


//Registration of user
exports.RegisterNewPage = (req, res) => {
    const {name, email, password, bio} = req.body;

    //Generating salt for Hashing
    const salt = genSaltSync(10);

    //Hashing the password
    const hashPassword = hashSync(password, salt);


    // Connecting to DB
    pool.getConnection((err, connection) => {
        if (err) {
            throw err;
        }
        else {
            connection.query('select email from users where email = ?', [email], (err, data) => {
                console.log(data)
                if (data.length != 0) {
                    res.render('register', {message: 'Already Registered'})

                }
                else{
                    connection.query('INSERT INTO users SET name = ?, email = ?, bio = ?, password = ?', [name, email, bio, hashPassword], (err, newRegisteredUser) => {
                        if(err){
                            res.render('register', {message: 'Something went wrong, Please try again'})
                        }
                        res.redirect('/auth/login/')
                    })
                }
            })


        }
    });
}

//Login the user
exports.Loginuser = (req,res) => {
    const {email, password} = req.body;
    pool.getConnection((err, connection) => {
        if (err) {
            throw err;
        }
        else {
            connection.query('SELECT * FROM users WHERE email = ?', [email], (err,data) => {
                if(err){
                    res.render('login', {message: 'Email or Password is Incorrect'});
                }
                if(data.length == 0){
                    res.render('login', {message: `Email Doesn't exist, Try to register`})
                }
                else{
                    const checkPassword = compareSync(password, data[0].password);
                    if(checkPassword){

                    //Creating the token for logged in user
                        const userToken = sign({result: data[0].email}, process.env.SECRET_KEY, {
                            expiresIn: '600s'
                        })

                        //Sending the token to user's cookie
                        res.cookie('userToken', userToken, {
                            expires: new Date(Date.now() + 600000),
                            httpOnly: true
                        })
                        console.log(userToken)
                        res.redirect('/')
                    };
                    else{
                        res.render('login', {message: 'Email or Password is Incorrect'})
                    };
                };
            });
        };
    });
};
Enter fullscreen mode Exit fullscreen mode

type the following code in homeControllers.js

const cookieParser = require('cookie-parser');
const { verify } = require('jsonwebtoken');
const mysql = require('mysql');
require('dotenv').config();

const pool = mysql.createPool({
    connectionLimit: 100,
    host: "localhost",
    user: "root",
    password: "",
    database: "users",
})

exports.HomePage = (req, res) => {
    const userToken = req.cookies.userToken;
    if (userToken) {
        verify(userToken, process.env.SECRET_KEY, (err, decoded) => {
            if (err) {
                res.render('home',{ notUser: true })
            }
            else {
                let userEmail = decoded.result;
                pool.getConnection((err, connection) => {
                    if (err) {
                        throw err;
                    }
                    else {
                        connection.query('SELECT * FROM users WHERE email = ?', [userEmail], (err,data) => {
                            res.render('home', {data})
                        })  
                    }
                });

            }
        })
    }
    else {
        res.render('home',{notUser: true})
    }
}


exports.userProfilePage = (req, res) => {
    const userToken = req.cookies.userToken;
    if (userToken) {
        verify(userToken, process.env.SECRET_KEY, (err, decoded) => {
            if (err) {
                res.redirect('/auth/login/')
            }
            else {
                let userEmail = decoded.result;
                pool.getConnection((err, connection) => {
                    if (err) {
                        throw err;
                    }
                    else {
                        connection.query('SELECT * FROM users WHERE email = ?', [userEmail], (err,data) => {
                            res.render('userProfile', {data})
                        })  
                    }
                });

            }
        })
    }
    else {
        res.redirect('/auth/login/')
    }
}
Enter fullscreen mode Exit fullscreen mode

Checking whether the user is Login Or Not:

type this code in userToken.js

const { verify } = require('jsonwebtoken');
require('dotenv').config()

exports.tokenValidation = (req,res,next) => {

    //geeting the stored cookie from user
    const userToken = req.cookies.userToken;
    if(userToken){

        //verifiying the stored cookie from user
        verify(userToken, process.env.SECRET_KEY, (err, decoded) => {
            if(err){
                res.redirect('/auth/login/')
            }
            else{
                // next will help to jump on next controller
                next()
            }
        })
    }
    else{
        res.redirect('/auth/login/')
    }
}
Enter fullscreen mode Exit fullscreen mode

Let's work with frontend:

Here I'm not providing the frontend code because that's simple HTML and CSS, you can create your own designing or still if you want my code then you can take it from my GitHub. User Login and Registration in NodeJS MySQL and JWT

Middleware explanation:

In the code I haven't explain, why we are using two middlewares in homeRoute.js, that's because first middleware is "validateToken", so when ever user request the route than before going to actual route the user will enter in validateToken and this will check whether the user is login or not if he is login then it will get access of 2nd middleware and if not then user will redirected to login page and user has to login, That's how we protected that route.

Still Having Doubt?

If you still have any doubt you can message me on Instagram or On LinkedIn:
Instagram: @rahulnikam.uiux

LinkedIn: Rahul Nikam (Recommended)

More by me

watch how to work with OAuth 2.0 Authentication using NodeJS, MySQL, JWT + ReactJS

Oldest comments (7)

Collapse
 
rahulnikam profile image
Rahul Nikam

If you have any doubt you can message me on LinkedIn, Link given at bottom of the article 👀

Collapse
 
davidluise profile image
ghostHunter

Thanks a lot. Rahul.
I had learned a lot from your article and your open project on github. I'd like to contact you.
Sincerely.
David Luis

Collapse
 
rahulnikam profile image
Rahul Nikam

Welcome David❣️🥂...why not you can message me on LinkedIn, Happy Coding!

Collapse
 
yanyiik99 profile image
yanyiik99

Thanks for your reference

Collapse
 
rahulnikam profile image
Rahul Nikam

You're welcome ❣️

Collapse
 
feisaladan profile image
Feisal-adan

Good Afternoon i am building school management system using Nodejs and mysql so i am facing my localhost:3000/login not showing my system rather showing error. and also when i run nodemon app.js command at command prompt. it show error like nodemon app.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter rs
[nodemon] watching path(s): .
[nodemon] watching extensions: js,mjs,json
[nodemon] starting node app.js index.js
Everything is fine
Connection Failed
GET / 304 43.416 ms - -
GET /stylesheets/styleforLogin.css 304 4.406 ms - -
GET /javascripts/jquerynav.min.js 304 2.073 ms - -
GET /javascripts/search.js 304 0.995 ms - -
GET /javascripts/pagination.js 304 1.220 ms - -
GET /javascripts/dropDownSearch.js 304 0.797 ms - -
GET /images/admin.png 304 0.719 ms - -
GET /images/bg.jpg 304 0.597 ms - -
GET /favicon.ico 404 12.407 ms - 150
User Name id Type of stringAnd Password is Type of string
Test Passed of Authentiacatoin
C:\Users\hp\Downloads\School-Nodejs-MySQL\routes\user\user.js:24
throw err;
^

Error: Cannot enqueue Query after fatal error.
at Protocol._validateEnqueue (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\mysql\lib\protocol\Protocol.js:212:16)
at Protocol._enqueue (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\mysql\lib\protocol\Protocol.js:138:13)
at Connection.query (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\mysql\lib\Connection.js:198:25)
at C:\Users\hp\Downloads\School-Nodejs-MySQL\routes\user\user.js:15:16
at Layer.handle as handle_request
at next (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\route.js:112:3)
at Layer.handle as handle_request
at C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\index.js:335:12) {
code: 'PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR',
fatal: false
}

Node.js v18.12.1
[nodemon] app crashed - waiting for file changes before starting...
[nodemon] restarting due to changes...
[nodemon] starting node app.js index.js
Everything is fine
Connection Failed
^C
C:\Users\hp\Downloads\School-Nodejs-MySQL>nodemon app.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter rs
[nodemon] watching path(s): .
[nodemon] watching extensions: js,mjs,json
[nodemon] starting node app.js index.js
Everything is fine
Connection Failed
User Name id Type of stringAnd Password is Type of string
Test Passed of Authentiacatoin
C:\Users\hp\Downloads\School-Nodejs-MySQL\routes\user\user.js:24
throw err;
^

Error: Cannot enqueue Query after fatal error.
at Protocol._validateEnqueue (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\mysql\lib\protocol\Protocol.js:212:16)
at Protocol._enqueue (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\mysql\lib\protocol\Protocol.js:138:13)
at Connection.query (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\mysql\lib\Connection.js:198:25)
at C:\Users\hp\Downloads\School-Nodejs-MySQL\routes\user\user.js:15:16
at Layer.handle as handle_request
at next (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\route.js:112:3)
at Layer.handle as handle_request
at C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\hp\Downloads\School-Nodejs-MySQL\node_modules\express\lib\router\index.js:335:12) {
code: 'PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR',
fatal: false
}

Node.js v18.12.1
[nodemon] app crashed - waiting for file changes before starting.. so please guide me through how can i move out of this stuck thanks.

Collapse
 
rahulnikam profile image
Rahul Nikam

check this - github.com/mysqljs/mysql/issues/832 if still uh are getting an err ping mee!