Skip to content

WebNinjaDeveloper.com

Programming Tutorials




Menu
  • Home
  • Youtube Channel
  • PDF Invoice Generator
Menu

Build a JWT Login & Registration Auth System in Node.js & Express Using MongoDB in Browser

Posted on March 30, 2023

 

 

Welcome folks today in this blog post we will be building the jwt authentication system in node.js and express using mongodb database in browser using javascript. All the full source code of the application is shown below.

 

 

BUY FULL SOURCE CODE

 

 

Get Started

 

 

In order to get started you need to make a new node.js project using the below command as shown below

 

 

npm init -y

 

 

And now after that we need to install all the dependencies which are needed for this project as shown below

 

 

npm i express

 

 

npm i jsonwebtoken

 

 

npm i mongoose

 

 

npm i bcrypt

 

 

npm i cookie-parser

 

 

npm i validator

 

 

npm i ejs

 

 

 

Express : This will be the web server which we will be using for our application

 

 

mongoose : It will be dependency which we will be using for interacting with the Mongodb database

 

 

bcrypt : This will be used for hashing the passwords

 

 

validator : This will be used for validating the data

 

 

ejs : This will be the view engine used for the application.

 

 

jsonwebtoken This library will generate and verify the json web token and let users login into the protected routes.

 

 

cookie-parser : This dependency will allow users to create and read cookies inside the express application

 

 

Directory Structure

 

 

At the end of this app this will be the directory structure you will be having as shown below

 

 

 

 

As you can see in the above directory structure of the project we are following the MVC approach which ensures all the code will be divided into their respective modules. Model will be the data used inside the application. View will be the different views used to render the app and the Controller will be the actual logic which will be used to make the Auth system. Apart from that we have also the Routes folder which will consist of all the routes used inside the express app. And middlewares folder will contain all the middleware or other functions used to make the app.

 

 

Starting a Basic Express App

 

 

Now guys we need to create the index.js file inside the root directory which will be the starting point of the project. And copy paste the below code to start a basic express app. And also we will be connecting to the Mongdb database as shown below

 

 

index.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const express = require("express");
const mongoose = require("mongoose");
const cookieParser = require("cookie-parser");
 
const app = express();
 
// middleware
app.use(express.static("public"));
app.use(express.json());
app.use(cookieParser());
 
// view engine
app.set("view engine", "ejs");
 
// database connection
const dbURI = "mongodb://localhost:27017/node-auth";
mongoose
  .connect(dbURI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
  })
  .then((result) => app.listen(3000))
  .catch((err) => console.log(err));

 

 

As you can see we are importing the mongoose module and then using the connect() method to connect to the database here you need to pass the database URL and then inside the callback function we are starting the express app at port 3000. And also we are passing different middlewares such as cookie-parser which is used to create and read cookies. And also we are making the public directory as static. Now you also need to create the public directory to hold the static files. We are also setting the view engine as ejs.

 

 

Defining the Views

 

 

Now guys inside the index.js file we need to define two routes which is specifically there to load the home page and the dashboard page as shown below

 

 

JavaScript
1
2
3
4
app.get("/", (req, res) => {
    res.render("login");
});
app.get("/dashboard",(req, res) => res.render("dashboard"));

 

 

Now we need to create the views folder and create this above files to allow the user to see the login page when he/she goes to the home page and see the dashboard page as well

 

 

views/login.ejs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%- include('partials/header'); -%>
 
<form>
  <h2>Login</h2>
  <label for="email">Email</label>
  <input type="text" name="email"  />
  <div class="email error"></div>
  <label for="password">Password</label>
  <input type="password" name="password"  />
  <div class="password error"></div>
  <button>login</button>
</form>
</body>
</html>

 

 

As you can see at the top we are loading the dynamic header file with the help of ejs and after that we have a basic html5 form where we have two fields to allow the user to enter the email and password and login button. Now we need to create the partials folder and inside it define the header.ejs file as shown below

 

 

 

 

partials/header.ejs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="/styles.css">
</head>
<body>
  <nav>
    <h1><a href="/">JWT Auth</a></h1>
    <ul>
        <li><a href="/login">Log in</a></li>
        <li><a href="/signup" class="btn">Sign up</a></li>
    </ul>
  </nav>

 

 

As you can see we are including the styles.css file at the top and then we have a simple nav where we have two buttons of login and signup.

 

 

Defining the CSS

 

 

Now we need to define the css for the login and register forms. For this inside the public folder create a styles.css file and copy paste the below code

 

 

public/styles.css

 

 

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
/* google fonts */
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap');
 
body{
  margin: 20px 40px;
  font-size: 1.2rem;
  letter-spacing: 1px;
  background: #fafafa;
}
h1, h2, h3, h4, ul, li, a, p, input, label, button, div, footer{
  margin: 0;
  padding: 0;
  font-family: 'Quicksand', sans-serif;
  color: #444;
}
ul{
  list-style-type: none;
}
a{
  text-decoration: none;
}
nav{
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 120px;
}
nav ul{
  display: flex;
  align-items: center;
}
nav li{
  margin-left: 20px;
}
nav li a{
  text-transform: uppercase;
  font-weight: 700;
  font-size: 0.8em;
  display: block;
  padding: 10px 16px;
  letter-spacing: 2px;
}
.btn{
  border-radius: 36px;
  background: #FEE996;
}
form h2{
  font-size: 2.4em;
  font-weight: 900;
  margin-bottom: 40px;
}
form{
  width: 360px;
  margin: 0 auto;
  padding: 30px;
  box-shadow: 1px 2px 3px rgba(0,0,0,0.1);
  border-radius: 10px;
  background: white;
}
input{
  padding: 10px 12px;
  border-radius: 4px;
  border: 1px solid #ddd;
  font-size: 1em;
  width: 100%;
}
label{
  display: block;
  margin: 20px 0 10px;
}
button{
  margin-top: 30px;
  border-radius: 36px;
  background: #FEE996;
  border:0;
  text-transform: uppercase;
  font-weight: 700;
  font-size: 0.8em;
  display: block;
  padding: 10px 16px;
  letter-spacing: 2px;
}
.error{
  color: #ff0099;
  margin: 10px 2px;
  font-size: 0.8em;
  font-weight: bold;
}
header{
  display: flex;
  align-items: center;
}
header img{
  width: 250px;
  margin-right: 40px;
}
header h2{
  font-size: 3em;
  margin-bottom: 10px;
}
header h3{
  font-size: 1.6em;
  margin-bottom: 10px;
  margin-left: 2px;
  color: #999;
}
header .btn{
  margin-top: 20px;
  padding: 12px 18px;
  text-transform: uppercase;
  font-weight: bold;
  display: inline-block;
  font-size: 0.8em;
}

 

 

And now if you see the login form it will look something as shown below

 

 

 

 

Similarly we need to create the register.ejs file and copy paste the following code which is shown below

 

 

signup.ejs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%- include('partials/header'); -%>
 
  <form>
    <h2>Sign up</h2>
    <label for="email">Email</label>
    <input type="text" name="email" required />
    <div class="email error"></div>
    <label for="password">Password</label>
    <input type="password" name="password" required />
    <div class="password error"></div>
    <button>Sign up</button>
  </form>
  </body>
  </html>

 

 

 

 

Now we will be creating the dashboard.ejs file which will be the protected page where only the authenticated users can access and see that page as shown below

 

 

dashboard.ejs

 

 

1
2
3
<%- include('partials/header'); -%>
 
<h1>This is the dashboard Account Page</h1>

 

 

 

Initializing Routes & Controllers

 

 

Now we will be initializing the different routes and controllers necessary for this auth system. For this you need to create the routes folder and inside it you need to create authRoutes.js file and also create a controllers folder and inside it create a authController.js file as shown below

 

 

routes/authRoutes.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
const { Router } = require('express');
const authController = require('../controllers/authController');
 
const router = Router();
 
router.get('/signup', authController.signup_get);
router.post('/signup', authController.signup_post);
router.post('/login', authController.login_post);
router.get('/logout', authController.logout_get);
 
module.exports = router;

 

 

As you can see we are having different routes or endpoints for different operations such as get request to login and signup pages using the express router. And same for post method as well. And here we are importing the controller file at the top and then using the methods defined in it in the routes. Now we need to define the controller file as well. Lastly here we are exporting the router from this file.

 

 

controllers/authController.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// controller actions
module.exports.signup_get = (req, res) => {
  res.render('signup');
}
 
module.exports.signup_post = async (req, res) => {
  res.send('new signup');
}
 
module.exports.login_get = (req,res) => {
  res.render('login')
}
 
module.exports.login_post = async (req, res) => {
  res.send('user login');
}

 

 

As you can see in the above code we have defined all the four methods that we have used inside the routes file for now we are just returning the simple messages for the post request. But later on we will be registering and logging the users. For the get requests we are rendering the `

 

 

Now at last we can include the authRoutes.js file inside the app.js file as shown below

 

 

app.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
const express = require('express');
const mongoose = require('mongoose');
const authRoutes = require('./routes/authRoutes');
 
const app = express();
 
// middleware
app.use(express.static('public'));
 
app.use(authRoutes);
 
// view engine
app.set('view engine', 'ejs');
 
// database connection
const dbURI = "mongodb://localhost:27017/node-auth";
mongoose
  .connect(dbURI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
  })
  .then((result) => app.listen(3000))
  .catch((err) => console.log(err));
 
// routes
app.get('/', (req, res) => res.render('login'));
app.get('/dashboard', (req, res) => res.render('dashboard'));

 

 

As you can see we are importing the file at the top and then we are passing it as a middleware using the use() method.

 

 

Defining the Model & Schema

 

 

Now guys we will be defining the models and the schema which will be used for this auth system. For this you need to make the models folder and create a User.js file as shown below

 

 

models/User.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const mongoose = require('mongoose');
 
const userSchema = new mongoose.Schema({
  email: {
    type: String,
    required: true,
    unique: true,
    lowercase: true,
  },
  password: {
    type: String,
    required: true,
    minlength: 6,
  }
});
 
const User = mongoose.model('user', userSchema);
 
module.exports = User;

 

 

As you can see we are importing the mongoose library at the top and then we are using the Schema method to define the schema which consists of email and password fields. And now we are also passing filters and validators for the data. And lastly we are using the model() method to create the table and also passing the schema which is defined earlier.

 

 

Inserting the User in MongoDB

 

 

Now guys after defining the model file we can import that file inside the controller and define the code of post method of login and signup routes as shown below

 

 

controllers/authController.js

 

 

JavaScript
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
const User = require("../models/User");
 
// controller actions
module.exports.signup_get = (req, res) => {
  res.render('signup');
}
 
module.exports.signup_post = async (req, res) => {
  const { email, password } = req.body;
 
  try {
    const user = await User.create({ email, password });
    res.status(201).json(user);
  }
  catch(err) {
    console.log(err);
    res.status(400).send('error, user not created');
  }
}
 
module.exports.login_post = async (req, res) => {
  const { email, password } = req.body;
 
  console.log(email, password);
  res.send('user login');
}

 

 

As you can see we are retrieving the json data passed by the user inside the post requests and extracting the email and password properties and then we are using the User.create() method to insert the email and the password into the Mongo Database. And then we are sending the json response back to the client.

 

 

Defining Custom Errors & Validating Data

 

 

Now inside the models file we can add our own custom error messages with the help of mongoose library as shown below

 

 

models/User.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const mongoose = require('mongoose');
const { isEmail } = require('validator');
 
const userSchema = new mongoose.Schema({
  email: {
    type: String,
    required: [true, 'Please enter an email'],
    unique: true,
    lowercase: true,
    validate: [isEmail, 'Please enter a valid email']
  },
  password: {
    type: String,
    required: [true, 'Please enter a password'],
    minlength: [6, 'Minimum password length is 6 characters'],
  }
});
 
const User = mongoose.model('user', userSchema);
 
module.exports = User;

 

 

 

Returning Errors as JSON to the Client

 

 

Now guys we can return the errors if user writes invalid data in the form of json to the client. For this you need to update the code inside the controller file as shown below

 

 

controllers/authController.js

 

 

JavaScript
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
const User = require("../models/User");
 
// handle errors
const handleErrors = (err) => {
  console.log(err.message, err.code);
  let errors = { email: '', password: '' };
 
  // incorrect email
  if (err.message === 'incorrect email') {
    errors.email = 'That email is not registered';
  }
 
  // incorrect password
  if (err.message === 'incorrect password') {
    errors.password = 'That password is incorrect';
  }
 
  // duplicate email error
  if (err.code === 11000) {
    errors.email = 'that email is already registered';
    return errors;
  }
 
  // validation errors
  if (err.message.includes('user validation failed')) {
    // console.log(err);
    Object.values(err.errors).forEach(({ properties }) => {
      // console.log(val);
      // console.log(properties);
      errors[properties.path] = properties.message;
    });
  }
 
  return errors;
}
 
// controller actions
module.exports.signup_get = (req, res) => {
  res.render('signup');
}
 
module.exports.signup_post = async (req, res) => {
  const { email, password } = req.body;
 
  try {
    const user = await User.create({ email, password });
    res.status(201).json(user);
  }
  catch(err) {
    const errors = handleErrors(err);
    res.status(400).json({ errors });
  }
}
 
module.exports.login_post = async (req, res) => {
  const { email, password } = req.body;
 
  console.log(email, password);
  res.send('user login');
}

 

 

As you can see we have define a separate function which is called handleErrors() and inside it we are extracting the error code and the actual error message and then storing it inside the error object and returning it. And then we are using the json() method to send the errors.

 

 

Hashing the Passwords

 

 

Now guys we will be hashing the plain text passwords that the user will submit for this we will be importing the bcrypt module. So we need to modify the code of the model file as shown below

 

 

models/User.js

 

 

JavaScript
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
const mongoose = require('mongoose');
const { isEmail } = require('validator');
const bcrypt = require('bcrypt');
 
const userSchema = new mongoose.Schema({
  email: {
    type: String,
    required: [true, 'Please enter an email'],
    unique: true,
    lowercase: true,
    validate: [isEmail, 'Please enter a valid email']
  },
  password: {
    type: String,
    required: [true, 'Please enter a password'],
    minlength: [6, 'Minimum password length is 6 characters'],
  }
});
 
 
// fire a function before doc saved to db
userSchema.pre('save', async function(next) {
  const salt = await bcrypt.genSalt();
  this.password = await bcrypt.hash(this.password, salt);
  next();
});
 
const User = mongoose.model('user', userSchema);
 
module.exports = User;

 

 

As you can see we are using the mongoose hooks function which is pre() it gets called everytime before when we save the data to the mongodb database. So here we are hashing the password using the bcrypt library.

 

 

 

 

Adding the Cookie-Parser Middleware

 

 

Now we need to import the cookie-parser library at the top and then we are passing the cookie-parser middleware to the express app inside the index.js file as shown below

 

 

index.js

 

 

JavaScript
1
2
3
4
5
const cookieParser = require("cookie-parser");
 
const app = express();
 
app.use(cookieParser());

 

 

Making the Login & Register HTML5 Forms

 

 

Now guys we will be using the html5 forms to allow the user to register and login . For this first of all we need to go authController.js file and copy paste the signUp code

 

 

controllers/authController.js

 

 

JavaScript
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
const User = require("../models/User");
const jwt = require('jsonwebtoken');
 
// create json web token
const maxAge = 3 * 24 * 60 * 60;
const createToken = (id) => {
  return jwt.sign({ id }, 'secret', {
    expiresIn: maxAge
  });
};
 
module.exports.signup_post = async (req, res) => {
  const { email, password } = req.body;
 
  try {
    const user = await User.create({ email, password });
    const token = createToken(user._id);
    res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 });
    res.status(201).json({ user: user._id });
  }
  catch(err) {
    const errors = handleErrors(err);
    res.status(400).json({ errors });
  }
}

 

 

As you can see we are importing the jsonwebtoken library at the top and then we are creating a new user using the create() method and then we are creating the jwt token and also passing the max_age for it. And then we are setting the token in the cookie.

 

And now we need to add the below ejs code inside the signup.ejs file as shown below

 

views/signup.ejs

 

 

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
<%- include('partials/header'); -%>
 
<form action="/signup">
  <h2>Sign up</h2>
  <label for="email">Email</label>
  <input type="text" name="email" required />
  <div class="email error"></div>
  <label for="password">Password</label>
  <input type="password" name="password" required />
  <div class="password error"></div>
  <button>Sign up</button>
</form>
 
<script>
  const form = document.querySelector('form');
  const emailError = document.querySelector('.email.error');
  const passwordError = document.querySelector('.password.error');
  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    // reset errors
    emailError.textContent = '';
    passwordError.textContent = '';
    // get values
    const email = form.email.value;
    const password = form.password.value;
    try {
      const res = await fetch('/signup', {
        method: 'POST',
        body: JSON.stringify({ email, password }),
        headers: {'Content-Type': 'application/json'}
      });
      const data = await res.json();
      console.log(data);
      if (data.errors) {
        emailError.textContent = data.errors.email;
        passwordError.textContent = data.errors.password;
      }
      if (data.user) {
        location.assign('/dashboard');
      }
    }
    catch (err) {
      console.log(err);
    }
  });
</script>
 
 
<%- include('partials/footer'); -%>

 

 

As you can see we are adding the javascript code to the form and inside it we are taking the values submitted by the user and then we are making the post request to the /signup route. We are making the fetch request to the backend and then we are passing the headers and also inside the body we are passing the email and the password. And also we are showing the validation errors as well from the json response coming back from the server. And also we are redirecting the user to the dashboard page.

 

 

 

 

Now we need to do the same thing for the login form as well. For this we need to edit the login.ejs file as shown below

 

 

Now before we write the html code for the login form we do need to write the code for comparing the password for the login form. If password is correct or not. For this we will be comparing the hashes of the password. For this we need to go to models/User.js file and add this code

 

 

models/User.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
// static method to login user
userSchema.statics.login = async function(email, password) {
  const user = await this.findOne({ email });
  if (user) {
    const auth = await bcrypt.compare(password, user.password);
    if (auth) {
      return user;
    }
    throw Error('incorrect password');
  }
  throw Error('incorrect email');
};

 

 

As you can see we have added the static method of login to the mongoDB Schema object. And inside it we are finding the user using the email provided and then we are comparing the hashes of the password.

 

 

And now we need to add the below code inside the authController.js file as shown below

 

 

controllers/authController.js

 

 

JavaScript
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
const User = require("../models/User");
const jwt = require('jsonwebtoken');
 
// create json web token
const maxAge = 3 * 24 * 60 * 60;
const createToken = (id) => {
  return jwt.sign({ id }, 'secret', {
    expiresIn: maxAge
  });
};
 
module.exports.login_post = async (req, res) => {
  const { email, password } = req.body;
 
  try {
    const user = await User.login(email, password);
    const token = createToken(user._id);
    res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 });
    res.status(200).json({ user: user._id });
  }
  catch (err) {
    const errors = handleErrors(err);
    res.status(400).json({ errors });
  }
}

 

 

As you can see in the above code we are adding the login method we are using the login() method of the model and then we are creating the jwt token and then we are inserting the token inside the cookie.

 

 

And now we need to add the ejs code inside the login.ejs file as shown below

 

 

views/login.ejs

 

 

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
<%- include('partials/header'); -%>
 
<form action="/signup">
  <h2>Login</h2>
  <label for="email">Email</label>
  <input type="text" name="email"  />
  <div class="email error"></div>
  <label for="password">Password</label>
  <input type="password" name="password"  />
  <div class="password error"></div>
  <button>login</button>
</form>
 
<script>
  const form = document.querySelector('form');
  const emailError = document.querySelector('.email.error');
  const passwordError = document.querySelector('.password.error');
 
  form.addEventListener('submit', async (e) => {
    e.preventDefault();
 
    // reset errors
    emailError.textContent = '';
    passwordError.textContent = '';
 
    // get values
    const email = form.email.value;
    const password = form.password.value;
 
    try {
      const res = await fetch('/login', {
        method: 'POST',
        body: JSON.stringify({ email, password }),
        headers: {'Content-Type': 'application/json'}
      });
      const data = await res.json();
      console.log(data);
      if (data.errors) {
        emailError.textContent = data.errors.email;
        passwordError.textContent = data.errors.password;
      }
      if (data.user) {
        location.assign('/dashboard');
      }
 
    }
    catch (err) {
      console.log(err);
    }
  });
</script>
 
</body>
</html>

 

 

As you can see we are once again making a post request using the fetch api and then sending the email and password to the /login route and then we are also showing the validation errors as well. And then redirecting to the /dashboard page when the user fills out the correct details.

 

 

 

 

Adding Auth Middlewares

 

 

Now we will be adding the auth middlewares which will be necessary to show the user details inside the dashboard page and also we are checking if the jwt token is present inside the cookie or not. Now we need to create the middlewares folder and inside it we need to make the authMiddleware.js file

 

 

middlewares/authMiddleware.js

 

 

JavaScript
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
const jwt = require('jsonwebtoken');
const User = require('../models/User');
 
const requireAuth = (req, res, next) => {
  const token = req.cookies.jwt;
 
  // check json web token exists & is verified
  if (token) {
    jwt.verify(token, 'secret', (err, decodedToken) => {
      if (err) {
        console.log(err.message);
        res.redirect('/login');
      } else {
        console.log(decodedToken);
        next();
      }
    });
  } else {
    res.redirect('/login');
  }
};
 
// check current user
const checkUser = (req, res, next) => {
  const token = req.cookies.jwt;
  if (token) {
    jwt.verify(token, 'secret', async (err, decodedToken) => {
      if (err) {
        res.locals.user = null;
        next();
      } else {
        let user = await User.findById(decodedToken.id);
        res.locals.user = user;
        next();
      }
    });
  } else {
    res.locals.user = null;
    next();
  }
};
 
 
module.exports = { requireAuth, checkUser };

 

 

As you can see we are defining two methods in which we check the current user if the jwt token is present inside the cookie or not and then we are verifying the token using the verify() method with the secret. And then we are setting the user to the res.locals property so that we can show the details inside the dashboard page. And then we have the requireAuth() method in which we redirect the user to the /dashboard page if the token is present inside the cookie.

 

 

Now we need to add the middlewares inside the index.js file as shown below

 

 

index.js

 

 

JavaScript
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
const express = require("express");
const mongoose = require("mongoose");
const jwt = require('jsonwebtoken')
const authRoutes = require("./routes/authRoutes");
const cookieParser = require("cookie-parser");
const { requireAuth, checkUser } = require("./middleware/authMiddleware");
 
const app = express();
 
// middleware
app.use(express.static("public"));
app.use(express.json());
app.use(cookieParser());
 
// view engine
app.set("view engine", "ejs");
 
// database connection
const dbURI = "mongodb://localhost:27017/node-auth";
mongoose
  .connect(dbURI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
  })
  .then((result) => app.listen(3000))
  .catch((err) => console.log(err));
 
// routes
app.get("*", checkUser);
app.get("/", (req, res) => {
  const token = req.cookies.jwt;
  if (token) {
    jwt.verify(token, "secret", (err, decodedToken) => {
      if (err) {
        res.render('login')
      } else {
        res.render('dashboard')
      }
    });
  } else {
    res.render("login");
  }
});
app.get("/dashboard", requireAuth, (req, res) => res.render("dashboard"));
app.use(authRoutes);

 

 

 

Showing User Details in Dashboard

 

 

Now we need to go to partials/header.ejs file and inside it we will be showing the user details and the logout button using some conditional rendering with the help of the ejs code as shown below

 

 

partials/header.ejs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="/styles.css">
</head>
<body>
  <nav>
    <h1><a href="/">JWT Auth</a></h1>
    <ul>
      <% if (user) { %>
        <li>Welcome, <%= user.email %></li>
        <li><a href="/logout">Log out</a></li>
      <% } else { %>
        <li><a href="/">Log in</a></li>
        <li><a href="/signup" class="btn">Sign up</a></li>
      <% } %>
    </ul>
  </nav>

 

 

 

 

 

Logout Users

 

 

Now lastly when user presses the logout button we will clear out the jwt token from the cookie and delete the cookie and redirect the user to the login page as shown below

 

 

controllers/authController.js

 

 

JavaScript
1
2
3
4
module.exports.logout_get = (req, res) => {
  res.cookie('jwt', '', { maxAge: 1 });
  res.redirect('/');
}

 

 

BUY FULL SOURCE CODE

 

 

Recent Posts

  • Node.js Express Project to Remove Background of Images Using Rembg & Formidable Library in Browser
  • Node.js Tutorial to Remove Background From Image Using Rembg & Sharp Library in Command Line
  • Python 3 Flask Project to Remove Background of Multiple Images Using Rembg Library in Browser
  • Python 3 Rembg Library Script to Bulk Process Multiple Images and Remove Background in Command Line
  • Python 3 Rembg Library Script to Remove Background From Image in Command Line
  • Angular
  • Bunjs
  • C#
  • Deno
  • django
  • Electronjs
  • java
  • javascript
  • Koajs
  • kotlin
  • Laravel
  • meteorjs
  • Nestjs
  • Nextjs
  • Nodejs
  • PHP
  • Python
  • React
  • ReactNative
  • Svelte
  • Tutorials
  • Vuejs




©2023 WebNinjaDeveloper.com | Design: Newspaperly WordPress Theme