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!
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');
});
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');
});
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;
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;
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'})
};
};
});
};
});
};
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/')
}
}
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/')
}
}
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
Top comments (7)
Thanks for your reference
You're welcome ❣️
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
Welcome David❣️🥂...why not you can message me on LinkedIn, Happy Coding!
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.
check this - github.com/mysqljs/mysql/issues/832 if still uh are getting an err ping mee!
If you have any doubt you can message me on LinkedIn, Link given at bottom of the article 👀