Welcome folks today in this blog post we will be building session based authentication
system using express-session
and cookie-parser
library in mongodb. All the full source code of the application is shown below.
Get Started
In order to get started you need to initialize a new node.js
project using the below command as shown below
npm i express
npm i cookie-parser
npm i express-session
npm i morgan
npm i mongoose
npm i bcrypt
And now you will see the below directory
structure of the node.js app as shown below
Now you need to make an index.js
file and copy paste the following code
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
var express = require("express"); var bodyParser = require("body-parser"); var cookieParser = require("cookie-parser"); var session = require("express-session"); var morgan = require("morgan"); var User = require("./models/User"); var app = express(); // set our application port app.set("port", 4000); // set morgan to log info about our requests for development use. app.use(morgan("dev")); // initialize body-parser to parse incoming parameters requests to req.body app.use(bodyParser.urlencoded({ extended: true })); // initialize cookie-parser to allow us access the cookies stored in the browser. app.use(cookieParser()); // initialize express-session to allow us track the logged-in user across sessions. app.use( session({ key: "user_sid", secret: "somerandonstuffs", resave: false, saveUninitialized: false, cookie: { expires: 600000, }, }) ); app.use((req, res, next) => { if (req.cookies.user_sid && !req.session.user) { res.clearCookie("user_sid"); } next(); }); // middleware function to check for logged-in users var sessionChecker = (req, res, next) => { if (req.session.user && req.cookies.user_sid) { res.redirect("/dashboard"); } else { next(); } }; // route for Home-Page app.get("/", sessionChecker, (req, res) => { res.redirect("/login"); }); // route for user signup app .route("/signup") .get(sessionChecker, (req, res) => { res.sendFile(__dirname + "/public/signup.html"); }) .post((req, res) => { }); // route for user Login app .route("/login") .get(sessionChecker, (req, res) => { res.sendFile(__dirname + "/public/login.html"); }) .post(async (req, res) => { } catch (error) { console.log(error) } }); // route for handling 404 requests(unavailable routes) app.use(function (req, res, next) { res.status(404).send("Sorry can't find that!"); }); // start the express server app.listen(app.get("port"), () => console.log(`App started on port ${app.get("port")}`) ); |
As you can see we are loading the login.html
and signup.html
and dashboard.html
template files when you go to /login
and /signup
and /dashboard
routes. And then we are using the express-session
middleware to check the status of the authentication. Now we need to make the public
folder and inside it you need to make the templates files
public/login.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<html> <head> <title>Login Here</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body class="container"> <div class="page-header"> <h1>Simple Auth-System</h1> </div> <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> <li><a href="/signup">Sign Up</a></li> <li><a href="/dashboard">Dashboard</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="/login">Log In</a></li> <li><a href="/logout">Log Out</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <div class="container row"> <div class="jumbotron col-sm-4 pull-center"> <form autocomplete="off" action="/login" method="post"> <div class="form-group"> <label>Username:</label> <input class="form-control" required type="text" name="username"/> </div> <div class="form-group"> <label>Password:</label> <input class="form-control" required type="password" name="password"/> </div> <div class="form-group"> <input class="btn btn-primary" type="submit" value="Log In"/> </div> </form> </div> </div> </body> </html> |
As you can see we are using the bootstrap cdn
and we have a simple user login
form where we can log the user in and then we have the simple button to submit the form.
Now we need to make the signup.html
file inside the public folder as shown below
public/signup.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<html> <head> <title>Login Here</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body class="container"> <div class="page-header"> <h1>Simple Auth-System</h1> </div> <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> <li><a href="/signup">Sign Up</a></li> <li><a href="/dashboard">Dashboard</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="/login">Log In</a></li> <li><a href="/logout">Log Out</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <div class="container row"> <div class="jumbotron col-sm-4 pull-center"> <form autocomplete="off" action="/signup" method="post"> <div class="form-group"> <label>Username:</label> <input class="form-control" required type="text" name="username"/> </div> <div class="form-group"> <label>Email:</label> <input class="form-control" required type="email" name="email"/> </div> <div class="form-group"> <label>Password:</label> <input class="form-control" required type="password" name="password"/> </div> <div class="form-group"> <input class="btn btn-primary" type="submit" value="Sign Up"/> </div> </form> </div> </div> </body> </html> |
Now we need to make the models
folder and inside it we will be storing the User.js
file which will store the schema
of the mongodb database as shown below
models/User.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
const mongoose = require('mongoose') const bcrypt = require('bcrypt') mongoose.connect("mongodb://localhost:27017/userDB",{ useNewUrlParser:true, useUnifiedTopology:true }) const userSchema = mongoose.Schema({ username:{ type:String, unique:true, required: true }, email:{ type:String, unique:true, required:true }, password:{ type:String, required:true } }) userSchema.pre("save", function(next) { if(!this.isModified("password")) { return next(); } this.password = bcrypt.hashSync(this.password, 10); next(); }); userSchema.methods.comparePassword = function(plaintext, callback) { return callback(null, bcrypt.compareSync(plaintext, this.password)); }; const userModel = mongoose.model('user',userSchema) module.exports = userModel |
As you can see we are using the mongoose
library to connect to the mongodb
database and then we have various user schema
rules for storing the username
and email and password and also we are using the bcrypt
module to hash the password and store it inside the mongodb database.
And now we need to modify the index.js
file and copy paste the below code
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
var express = require("express"); var bodyParser = require("body-parser"); var cookieParser = require("cookie-parser"); var session = require("express-session"); var morgan = require("morgan"); var User = require("./models/User"); var app = express(); // set our application port app.set("port", 4000); // set morgan to log info about our requests for development use. app.use(morgan("dev")); // initialize body-parser to parse incoming parameters requests to req.body app.use(bodyParser.urlencoded({ extended: true })); // initialize cookie-parser to allow us access the cookies stored in the browser. app.use(cookieParser()); // initialize express-session to allow us track the logged-in user across sessions. app.use( session({ key: "user_sid", secret: "somerandonstuffs", resave: false, saveUninitialized: false, cookie: { expires: 600000, }, }) ); // This middleware will check if user's cookie is still saved in browser and user is not set, then automatically log the user out. // This usually happens when you stop your express server after login, your cookie still remains saved in the browser. app.use((req, res, next) => { if (req.cookies.user_sid && !req.session.user) { res.clearCookie("user_sid"); } next(); }); // middleware function to check for logged-in users var sessionChecker = (req, res, next) => { if (req.session.user && req.cookies.user_sid) { res.redirect("/dashboard"); } else { next(); } }; // route for Home-Page app.get("/", sessionChecker, (req, res) => { res.redirect("/login"); }); // route for user signup app .route("/signup") .get(sessionChecker, (req, res) => { res.sendFile(__dirname + "/public/signup.html"); }) .post((req, res) => { var user = new User({ username: req.body.username, email: req.body.email, password:req.body.password, }); user.save((err, docs) => { if (err) { res.redirect("/signup"); } else { console.log(docs) req.session.user = docs; res.redirect("/dashboard"); } }); }); // route for user Login app .route("/login") .get(sessionChecker, (req, res) => { res.sendFile(__dirname + "/public/login.html"); }) .post(async (req, res) => { var username = req.body.username, password = req.body.password; try { var user = await User.findOne({ username: username }).exec(); if(!user) { res.redirect("/login"); } user.comparePassword(password, (error, match) => { if(!match) { res.redirect("/login"); } }); req.session.user = user; res.redirect("/dashboard"); } catch (error) { console.log(error) } }); // route for user's dashboard app.get("/dashboard", (req, res) => { if (req.session.user && req.cookies.user_sid) { res.sendFile(__dirname + "/public/dashboard.html"); } else { res.redirect("/login"); } }); // route for user logout app.get("/logout", (req, res) => { if (req.session.user && req.cookies.user_sid) { res.clearCookie("user_sid"); res.redirect("/"); } else { res.redirect("/login"); } }); // route for handling 404 requests(unavailable routes) app.use(function (req, res, next) { res.status(404).send("Sorry can't find that!"); }); // start the express server app.listen(app.get("port"), () => console.log(`App started on port ${app.get("port")}`) ); |
And now we need to add the dashboard.html
template file where the user will get redirected once the user has been successfully authenticated
and we welcome the user inside the dashboard
public/dashboard.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<html> <head> <title>Login Here</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body class="container"> <div class="page-header"> <h1>Simple Auth-System</h1> </div> <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> <li><a href="/signup">Sign Up</a></li> <li><a href="/dashboard">Dashboard</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="/login">Log In</a></li> <li><a href="/logout">Log Out</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <div class="container row"> <h1>Hi, Welcome to your Dashboard</h1> </div> </body> </html> |