You will see a message saying the “Server started running at port: 3000”. You can access your server from the following URL:
http://localhost:3000
Now, we need to install the module for displaying views. And to get input from form fields. So, install the following modules:
> npm install ejs fs express-formidable
EJS module is used for displaying the HTML files. FS stands for File System, this module is used to handle files. And “express-formidable” is used for getting values from the input field. Make sure to run the “nodemon server.js” command again.
Install compress image module in Node JS
To install a module to compress image in Node JS, you need to run the following command in your terminal:
Now, write the following lines in the [get route goes here] section:
app.get("/", function (request, result) {
result.render("index")
})
After that, you need to create a folder named “views” at the root of your project. And in that folder, create a file named “index.ejs”. Following will be the code of “index.ejs”:
It will display a simple HTML form with an input field and a submit button. Then, you need to create a POST route that will handle this request. The following code goes in the [post route goes here] section of the “server.js” file:
app.post("/compressImage", function (request, result) {
const image = request.files.image
if (image.size > 0) {
if (image.type == "image/png" || image.type == "image/jpeg") {
fileSystem.readFile(image.path, function (error, data) {
if (error) throw error
const filePath = "temp-uploads/" + (new Date().getTime()) + "-" + image.name
const compressedFilePath = "uploads/"
const compression = 60
fileSystem.writeFile(filePath, data, async function (error) {
if (error) throw error
compressImages(filePath, compressedFilePath, { compress_force: false, statistic: true, autoupdate: true }, false,
{ jpg: { engine: "mozjpeg", command: ["-quality", compression] } },
{ png: { engine: "pngquant", command: ["--quality=" + compression + "-" + compression, "-o"] } },
{ svg: { engine: "svgo", command: "--multipass" } },
{ gif: { engine: "gifsicle", command: ["--colors", "64", "--use-col=web"] } },
async function (error, completed, statistic) {
console.log("-------------")
console.log(error)
console.log(completed)
console.log(statistic)
console.log("-------------")
fileSystem.unlink(filePath, function (error) {
if (error) throw error
})
}
)
result.send("File has been compressed and saved.")
})
fileSystem.unlink(image.path, function (error) {
if (error) throw error
})
})
} else {
result.send("Please select an image")
}
} else {
result.send("Please select an image")
}
})
The last thing you need to do is to create two folders named “uploads” and “temp-uploads” at the root of your project. Here, all compressed images will be stored.
This will compress the image up to 60%. You can now try to select an image from the input file and hit “Compress image”. You will see a success message if everything goes right. And you will see your compressed image in the “uploads” folder.
Real-world example
We implemented this compression in one of our projects, so you can get the real-world example of image compression in Node JS.
So that’s how you can compress an image in Node JS. If you face any problems in following this, kindly do let us know.
In this tutorial, we are going to teach you, how you can encrypt and decrypt the strings using Node JS and Mongo DB. The encrypted strings will be saved in the database and upon retrieval will be decrypted.
Setup the Project
First, create an empty folder and open a command prompt in it. Then run the following commands in it one by one:
crypto module will be used to encrypt and decrypt the strings. ejs module will be used to render HTML files. Then create a file named server.js at the root of folder. Open server.js file and write the following code in it:
// initialize express JS
const express = require("express");
const app = express();
// create HTTP server
const http = require("http").createServer(app);
// [include Mongo DB module here]
// start the server
http.listen(process.env.PORT || 3000, function () {
console.log("Server started running...");
// [connect with Mongo DB here]
});
Open your terminal and you will see the message that the server has been started. You can access your project at http://localhost:3000/
Setup Mongo DB
Write the following lines in place of [include Mongo DB module here] section in your server.js file:
// include mongo DB
var mongodb = require("mongodb");
var MongoClient = mongodb.MongoClient;
Then connect the database in the [connect with Mongo DB here] section:
// connect with mongo DB server
MongoClient.connect("mongodb://localhost:27017", function (error, client) {
if (error) {
console.error(error);
return;
}
// set database
db = client.db("encrypt_decrypt_string");
console.log("Database connected");
// [routes goes here]
});
Save the file and open your terminal, now you will see another message that the database has been connected as well.
Encrypt the String
First, include the crypto module at the top of your server.js file:
// include crypto module
const crypto = require("crypto")
// set encryption algorithm
const algorithm = 'aes-256-cbc'
// private key
const key = "adnan-tech-programming-computers" // must be of 32 characters
// random 16 digit initialization vector
const iv = crypto.randomBytes(16)
The key and initialization vector can be any string of 32 and 16 characters respectively. But it is recommended to keep the key hard-coded and initialization vector to be random. Because IV will be saved in database.
We cannot save the key in the database, because if the database gets hacked then all your encrypted strings will be compromised as well.
After that, create a GET route that will encrypt the string and save in Mongo DB. Write the following code in the [routes goes here] section:
// route to encrypt the message
app.get("/encrypt/:message", async function (request, result) {
// get message from URL
const message = request.params.message;
// random 16 digit initialization vector
const iv = crypto.randomBytes(16);
// encrypt the string using encryption algorithm, private key and initialization vector
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encryptedData = cipher.update(message, "utf-8", "hex");
encryptedData += cipher.final("hex");
// convert the initialization vector to base64 string
const base64data = Buffer.from(iv, 'binary').toString('base64');
// save encrypted string along wtih initialization vector in database
await db.collection("strings").insertOne({
iv: base64data,
encryptedData: encryptedData
});
// show the encrypted message
result.send(encryptedData);
});
You can write any string in the URL and you will see the encrypted text in the browser and also in your Mongo DB.
Show all Encrypted Strings
To show all encrypted strings, we are going to use a module named ejs. Write the following line at the top of your server.js file:
// set templating engine as EJS
app.set("view engine", "ejs");
The create the following GET route to show all encrypted strings:
// route to show all encrypted messages
app.get("/", async function (request, result) {
// get all data from database
const data = await db.collection("strings")
.find({})
.sort({
_id: -1
}).toArray();
// render index.ejs
result.render("index", {
data: data
});
});
Create a new folder named views and inside it create a file named index.ejs. It will have the following code:
<table>
<% for (let d in data) { %>
<tr>
<td>
<a href="/decrypt/<%= data[d].encryptedData %>" target="_blank">
<%= data[d].encryptedData %>
</a>
</td>
</tr>
<% } %>
</table>
Access the URL: http://localhost:3000/ and you will see all your encrypted strings in descending order.
Decrypt the String
To decrypt the string, create a GET route and fetch the encrypted string and initialization vector from Mongo DB. Then we can apply the decryption using key.
// route to decrypt the message
app.get("/decrypt/:encrypted", async function (request, result) {
// get encrypted text from URL
const encrypted = request.params.encrypted;
// check if text exists in database
const obj = await db.collection("strings").findOne({
encryptedData: encrypted
});
if (obj == null) {
result.status(404).send("Not found");
return;
}
// convert initialize vector from base64 to buffer
const origionalData = Buffer.from(obj.iv, 'base64')
// decrypt the string using encryption algorithm and private key
const decipher = crypto.createDecipheriv(algorithm, key, origionalData);
let decryptedData = decipher.update(obj.encryptedData, "hex", "utf-8");
decryptedData += decipher.final("utf8");
// display the decrypted string
result.send(decryptedData);
});
If you click on any string now, you will see the actual string.
Picture Competition is a mobile responsive real-time web application developed in Node JS and Mongo DB. Its frontend is designed in Bootstrap and Vue JS. You can create competition between 2 people and the others can vote on the person based on looks or skills etc.
It uses login authentication using JWT (JsonWebToken). It does not use the browser session due to the following reasons:
Sessions are destroyed once your app is restarted from terminal.
Sessions are not linked with the server, they are stored in browser only.
The benefit of using JWT is that you can always log out a user from your Mongo DB. Just go to the “users” collection and find the specific user. Then empty the “accessToken” field of that user’s document.
Login and Registration
2. Create Competitions
Registered users can create competitions between 2 users. You can enter name and upload 1 picture of each competitor. There is no limit in the number of competitions to create, you can create as many as you want. You can view your created competitions on your “My Competitions” page.
As soon as you create a competition, it will automatically be displayed to all the users as well as to the admin in real-time. Users do not have to refresh the page to see new competitions. It uses Socket IO to display data in real-time.
Create Competition
3. Search
Users can search competitions by the name of competitors. Data is filtered and rendered using Vue JS. There is no need to press the enter key, the data is filtered as soon as the user starts typing in the search box.
Search and Sort
4. Sort
Users can also sort the competitions by any of the following for sorting functions:
Highest votes to lowest.
Lowest votes to highest.
Oldest to newest.
Newest to oldest (default).
5. Vote on Competition
Logged-in users can vote on the competition. You can either vote on one of the competitors. Once the vote is cast on one competitor, it cannot be removed. Also, you can cast your vote on only one of the competitors, not on both of them. It is also real-time, as soon as the vote is cast, it will automatically be displayed to all the users and the counter is incremented. The counter displays the number of votes cast on each competitor.
Votes
6. Delete Competition
Competitions can only be deleted by either of the users who created the competition, or by the admin. Once the competition is deleted, all the uploaded images will be deleted too. As soon as the competition is deleted, it will automatically be removed from all the other users too, without having them refresh the page.
7. Realtime Update using Sockets
Sockets are used for real-time communication. Instead of fetching the data from the server after regular intervals, sockets attach listeners to the client-side. Listeners are listening to the events sent from the server. The server will emit the event and the client will listen to that event and respond accordingly. In this project, sockets are used for the following features:
When competition is created.
When competition is deleted.
To increase the counter after vote is casted to the competition.
Notifications.
8. Notifications
When a competition is deleted by the admin, the admin will write the reason for the deletion. Thus, a notification will be sent to the user along with the reason why his competition was removed. By default, notification status is “unread” and they are highlighted. As soon as the user clicks on any of the notifications, that notification will be marked as “read” and it will no longer be highlighted.
Notifications
9. Load More Button
When the data in the database increases, it is not feasible to load all the data in a single AJAX request. So a “load more” button is created to solve this problem. For example, 10 records are fetched in the first AJAX request. The next 10 records will be fetched when the “load more” button is clicked, and so on.
Load More
10. Admin Panel
Admin panel is created so you (administrator) can delete any competition you find offensive. The default email and password of admin are:
email = admin@gmail.com password = admin
11. Manage Competitions
Admin can delete competitions that he finds offensive. However, the admin must give the reason why that competition is deleted. A notification will be sent to the user who created that competition and he will be able to view it from the top navigation bar.
12. Reset Password
Now you will be able to reset your password if you ever forgot. You just need to enter your email address and an email will be sent to you with a link to reset the password. We are using the nodemailer module to send an email.
Forgot PasswordReset Password
13. Email Verification
When a new user registers, we are sending a verification email to the user’s entered email address. The user will not be able to log in until he verifies his email address. When a user clicks the link on his email address, he will receive a message that says that his account is verified. Then he will be able to log in successfully.
Email Verification
14. SMTP Configurations from Admin Panel
To send an email, you will need an SMTP server. Every SMTP server requires some configurations to set up that include, host, port, email, and password. You can write these values directly hardcoded in your code, but to update these values in the future, you have to find these values in the code and update them.
In this project, you can set these configurations directly from the admin panel. Once the values are set, new emails will be sent using the new configurations.
SMTP configurations from admin panel
15. Adult Image Validation
This is a must-have feature if you are creating a website that allows users to upload pictures and they will be seen to the world. Anyone can upload an image that contains adult content, and it will not be good for your business. So when the user is uploading pictures while creating competition, the system will automatically check if the image is safe to upload.
If the image is an adult image, then an error will be shown to the user and it will not be uploaded.
16. Admin Panel Stats
Admin can see total users, total competitions, and total votes cast so far. They are also real-time, so when a new user is registered, or new competition is created, or event a new vote is cast, it will automatically be incremented here.
Also, when competition is deleted, the number will automatically get decremented as well, without having the admin refresh the page.
Admin Panel Stats
17. Real-time Comments
Users can comment on each competition. And they are also real-time as well. Once a new comment is added, it will immediately be displayed to all the other users as well. They do not have to refresh the page to see new comments.
Real-time Comments
18. User Profile
Users can now update their names and profile pictures. We are using the fs (file system) module to upload the picture. User can also add their bio, date of birth, country, and social media links. Media links include Facebook, Instagram, google plus, Twitter, and LinkedIn.
User can also change their account password. In order to change the password, the user must enter the current password. The new password should be entered twice for confirmation.
User Profile
19. Free Customer Support
This is not a feature of the project, but it is a free service provided for the pro version only. That means if you find any difficulty in installing or configuring the project, we will help you install it. Also, if you encounter any error or a bug in the released version, then it can be fixed too.
These are all the features we have right now in the picture competition web app. We are open to more ideas. If you have more ideas to add, kindly do let us know.
This tutorial will discuss how you can create a JWT authentication system (Login, Registration, and Logout) using JSON Web Token in Node JS and Mongo DB. You can follow the video below if you prefer a video tutorial:
First, make sure you have downloaded and installed Node JS and Mongo DB. You can also download Mongo DB Compass to view the database.
Setup the Project
First, create an empty folder anywhere on your computer and open the command prompt in it. Once CMD is open inside the folder, run the following command:
express: A framework used for better routing, middleware etc.
express-formidable: To get the values from AJAX.
mongodb: To interact with database.
http: To handle HTTP requests.
bcrypt: To encrypt and decrypt the password.
jsonwebtoken: To generate JSON Web Token used for authentication.
ejs: View engine to display HTML pages.
Now, create a file named “server.js” at the root of your folder. To start the server you can use the following command:
node server.js
But every time you made some changes in the server.js file, you have to run that command again. To prevent this, you can install the nodemon module using the following command:
npm install -g nodemon
Then you can use the following command to keep the server running:
nodemon server.js
Start the Server
Open your server.js file and write the following code in it:
// include express module
var express = require("express");
// create instance of express
var app = express();
// use express-formidable middleware
var formidable = require("express-formidable");
app.use(formidable());
// include mongodb module
var mongodb = require("mongodb");
// get mongodb client
var mongoClient = mongodb.MongoClient;
// get ObjectId, it is unique for each document
var ObjectId = mongodb.ObjectId;
// create http server from express instance
var http = require("http").createServer(app);
// include bcrypt module
var bcrypt = require("bcrypt");
// include jsonwebtoken module
var jwt = require("jsonwebtoken");
// random secret string
var accessTokenSecret = "myAccessTokenSecret1234567890";
// use public folder for css and js files
app.use(express.static(__dirname + "public"));
// use ejs engine to render html files
app.set("view engine", "ejs");
var mainURL = "http://localhost:3000";
// start the server at port 3000
http.listen(3000, function () {
console.log("Server started.");
// connect with mongodb
mongoClient.connect("mongodb://localhost:27017", function (error, client) {
// database name will be "jwt_authentication"
var database = client.db("jwt_authentication");
console.log("Database connected");
});
});
This will include all the necessary modules and start the server at port 3000. The module used for JWT authentication is named jsonwebtoken. You can access it from your browser with the following link:
http://localhost:3000/
You will see an error because there isn’t any route for the home page. Open your CMD and you will see 2 messages:
“Server started.”
“Database connected”
If you open the Mongo DB Compass you will not see a database. Because database will be created only there is at least one collection in it. So our database will be created when there is at least one user in our database.
User Registration
Go to the following address in your browser:
http://localhost:3000/signup
First, we are going to create a route in our server.js right after the database is connected.
server.js
// route for signup requests
app.route("/signup")
// get request accessed from browser
.get(function (request, result) {
// render signup.ejs file inside "views" folder
result.render("signup");
});
Now we need to create a folder named views at our root folder. Inside this folder, create a file named signup.ejs (note the extension). Also create 2 more files, header.ejs and footer.ejs.
header.ejs
<!-- menu items will be created using Javascript -->
<ul id="main-menu">
</ul>
<script>
// variables used in all files
var mainURL = "http://localhost:3000";
var accessTokenKey = "accessToken";
var user = null;
</script>
<script>
function doRegister(form) {
// disable the submit button and show "Loading..." text
form.submit.setAttribute("disabled", "disabled");
form.submit.value = "Loading...";
// create AJAX object
var ajax = new XMLHttpRequest();
// 1. method is POST
// 2. path where request will be sent
// 3. request will be asynchronous
ajax.open("POST", mainURL + "/signup", true);
// called everytime status of request changes
ajax.onreadystatechange = function () {
// when response is received from server
if (this.readyState == 4) {
// if the request is OK
if (this.status == 200) {
// response received from server
console.log(this.responseText);
// enable the submit button
form.submit.removeAttribute("disabled");
form.submit.value = "Register";
// convert the JSON string into Javascript object
var response = JSON.parse(this.responseText);
// display message
alert(response.message);
// if the user is created, then redirect to login
if (response.status == "success") {
window.location.href = "/login";
}
}
// if there is an internal server error
if (this.status == 500) {
console.log(this.responseText);
}
}
};
// create form data object from form
var formData = new FormData(form);
// actually sending the AJAX request
ajax.send(formData);
// prevent the form from submitting
return false;
}
</script>
This will show a form with input fields for name, email and password. Now we need to create a POST route in our server.js. We will chain the POST route after our “/signup” GET route.
// route for signup requests
app.route("/signup")
// get request accessed from browser
.get(function (request, result) {
// render signup.ejs file inside "views" folder
result.render("signup");
})
// post request called from AJAX
.post(async function (request, result) {
// get values from signup form
var name = request.fields.name;
var email = request.fields.email;
var password = request.fields.password;
// check if email already exists
var user = await database.collection("users").findOne({
"email": email
});
if (user != null) {
result.json({
"status": "error",
"message": "Email already exists."
});
return true;
}
// encrypt the password
bcrypt.hash(password, 10, async function (error, hash) {
// insert in database
await database.collection("users").insertOne({
"name": name,
"email": email,
"password": hash,
"accessToken": ""
});
// send the response back to client
result.json({
"status": "success",
"message": "Signed up successfully. You can login now."
});
});
});
If you run the code now, you will see a registration form. You can enter your name, email, and password and hit enter. The first time, you will see a success message and you will be redirected to the login route. You can refresh your Mongo DB Compass, and you will see your database and one collection of “users”. Inside this collection, you will see your document inserted. If you enter the same email again, you will get an error.
User Login – JWT authentication
Go to the following address in your browser:
http://localhost:3000/login
First, we are going to create a route in our server.js right after the signup route.
server.js
// route for login requests
app.route("/login")
// get request accessed from browser
.get(function (request, result) {
// render login.ejs file inside "views" folder
result.render("login");
});
Then create a file named login.ejs and write the following code in it:
<script>
function doLogin(form) {
// disable the submit button and show "Loading..." text
form.submit.setAttribute("disabled", "disabled");
form.submit.value = "Loading...";
// create AJAX object
var ajax = new XMLHttpRequest();
// 1. method is POST
// 2. path where request will be sent
// 3. request will be asynchronous
ajax.open("POST", mainURL + "/login", true);
// called everytime status of request changes
ajax.onreadystatechange = function () {
// when response is received from server
if (this.readyState == 4) {
// if the request is OK
if (this.status == 200) {
// response received from server
console.log(this.responseText);
// enable the submit button
form.submit.removeAttribute("disabled");
form.submit.value = "Login";
// convert the JSON string into Javascript object
var response = JSON.parse(this.responseText);
// if user is logged in successfully
if (response.status == "success") {
// get access token from server
var accessToken = response.accessToken;
// save in local storage
localStorage.setItem("accessToken", accessToken);
// redirect to home page
window.location.href = "/";
} else {
// display message
alert(response.message);
}
}
// if there is an internal server error
if (this.status == 500) {
console.log(this.responseText);
}
}
};
// create form data object from form
var formData = new FormData(form);
// actually sending the AJAX request
ajax.send(formData);
// prevent the form from submitting
return false;
}
</script>
This will show a form with input fields for email and password. Now we need to create a POST route in our server.js. We will chain the POST route after our “/login” GET route.
// route for login requests
app.route("/login")
// get request accessed from browser
.get(function (request, result) {
// render login.ejs file inside "views" folder
result.render("login");
})
// post request called from AJAX
.post(async function (request, result) {
// get values from login form
var email = request.fields.email;
var password = request.fields.password;
// check if email exists
var user = await database.collection("users").findOne({
"email": email
});
if (user == null) {
result.json({
"status": "error",
"message": "Email does not exists."
});
return false;
}
// check if password is correct
bcrypt.compare(password, user.password, async function (error, isVerify) {
if (isVerify) {
// generate JWT of user
var accessToken = jwt.sign({
"email": email
}, accessTokenSecret);
// update JWT of user in database
await database.collection("users").findOneAndUpdate({
"email": email
}, {
$set: {
"accessToken": accessToken
}
});
result.json({
"status": "success",
"message": "Login successfully.",
"accessToken": accessToken
});
return false;
}
result.json({
"status": "error",
"message": "Password is not correct."
});
});
});
If you run the code now, you will see a login form. You can enter your email and password and hit enter. If the credentials are correct, then it will save the access token in your local storage in your browser, and you will be redirected to the home page. You can refresh your Mongo DB Compass, and you will see that the accessToken field of the user has been updated. If you enter the wrong credentials, then it will not update the database.
Home Page
Now we need to create a route for our home page in server.js:
// route for home page
app.get("/", function (request, result) {
result.render("index");
});
Create a file named index.ejs inside views folder and write the following code in it:
<%- include ("header") %>
<%- include ("footer") %>
Now comes the footer part. Following will be the code of your footer.ejs file:
footer.ejs
<script>
// get user on page load
window.addEventListener("load", function () {
getUser();
});
function getUser() {
// check if user is logged in
if (localStorage.getItem(accessTokenKey)) {
// call AJAX to get user data
var ajax = new XMLHttpRequest();
ajax.open("POST", mainURL + "/getUser", true);
ajax.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
// console.log(this.responseText);
var response = JSON.parse(this.responseText);
if (response.status == "success") {
// user is logged in
window.user = response.user;
} else {
// user is logged out
localStorage.removeItem(accessTokenKey);
}
showMainMenu();
}
if (this.status == 500) {
console.log(this.responseText);
}
}
};
var formData = new FormData();
formData.append("accessToken", localStorage.getItem(accessTokenKey));
ajax.send(formData);
return false;
}
showMainMenu();
}
function doLogout() {
// send beacon to server before redirecting
var formData = new FormData();
formData.append("accessToken", localStorage.getItem(accessTokenKey));
navigator.sendBeacon(mainURL + "/logout", formData);
// remove access token from local storage
localStorage.removeItem(accessTokenKey);
return true;
}
function showMainMenu() {
var html = "";
// if user is logged in
if (localStorage.getItem(accessTokenKey)) {
html += `<li>
<a href='/login' onclick='return doLogout();'>Logout</a>
</li>`;
} else {
html += `<li>
<a href='/login'>Login</a>
</li>`;
html += `<li>
<a href='/signup'>Signup</a>
</li>`;
}
// show in main menu
document.getElementById("main-menu").innerHTML = html;
}
</script>
This will show login and signup links if the user is not logged in. If the user is logged in, then it will display a logout button. When the logout button is clicked, it will be redirected to the “/login” route. But before redirecting, it will send a beacon to the server to empty the accessToken field in the database. So we need to create POST routes for “/getUser” and for “/logout”:
// return user data using access token
app.post("/getUser", async function (request, result) {
var accessToken = request.fields.accessToken;
var user = await database.collection("users").findOne({
"accessToken": accessToken
});
if (user == null) {
result.json({
"status": "error",
"message": "User has been logged out. Please login again."
});
return false;
}
result.json({
"status": "success",
"message": "Data has been fetched.",
"user": user
});
});
// empty the access token of user (logout)
app.post("/logout", async function (request, result) {
var accessToken = request.fields.accessToken;
await database.collection("users").findOneAndUpdate({
"accessToken": accessToken
}, {
$set: {
"accessToken": ""
}
});
result.json({
"status": "success",
"message": "User has been logged out."
});
});
With that, your authentication is completed. You can log in and log out now. Once you log out and refresh the Mongo DB Compass, you will see the accessToken field becomes empty. And it will again have the value once the user logged in again.
Why we used Beacon ?
You might have noticed that we have used Beacon instead of AJAX when the logout button is clicked. The reason for this is when the browser navigates from one page to another, the AJAX calls are sometimes aborted by the browser. To prevent this, we use beacons.
Get Data using AJAX
Now that your authentication system is done, you might want to show data to logged-in users only. So for example, you have a blogging website and you want to show your blog posts to logged-in users only. So you need to do the following steps.
1) Create Variable and a Function
In the file where you want to fetch and display the data, create the following variable and a function in Javascript.
<script>
var onPostsPage = true;
function getPosts() {
// call ajax
}
</script>
If you want to learn how to call an AJAX request and show data from it, follow this tutorial.
2) Call Function if Variable is Set
In your footer.ejs, when the user is logged-in, check if this variable is set and is true. If yes, then simply call that function.
// user is logged in
window.user = response.user;
if (typeof onPostsPage !== "undefined" && onPostsPage) {
getPosts();
}
So, that’s how you can create a JWT authentication system In Node JS and Mongo DB.