Hey, Developers! In This Blog Post, We Will See How To Use Jwt Authentication In Express.js With Mongodb, Step By Step. Jwt Is A Popular Way To Securely Transmit Information Between The Backend Of Our Website To The User.
Jwt Offers You Secure Authentication By Creating A Token That Verifies A User’s Identity. Understanding Jwt Authentication Is Important As It Helps To Protect Your Application & User Data By Ensuring That Only Authorized Users Can Access Specific Pages Of Your App.
Also Read: How To Set & Get Cookies In Express With MongoDB
While There Are Many Ways To Handle Authentication, Using Jwts In An Express Application With Mongodb Provides A Scalable And Efficient Method. In This Blog Post, I Will Show How You Can Use Jwt Authentication In Express Applications From Setting Up The File To Testing The Authentication.
In This Comprehensive Post, We Will Create Two Fixed Endpoints For Login & Signup Where Users Can Log In And Sign Up Respectively. When A User Creates An Account ( Sign Up ) We Will Create One Document In The Mongodb.
After The Creation Of The Document, We Will Redirect The User To The Login Page. Where User Can Enter His Credentials. Once He Enters The Right Credentials We Will Create A JSON Web Token And Send It In The Form Of A Cookie So That We Can Check Before He Enters The Authenticated Page.
JWT Stands For JSON Web Token Which Can Be Signed & Encrypted For Authentication And Authorization Of The Web Application. The Advantages Of JWT Are As Follows:
First, we will start our project by creating one folder called “JWT” on the desktop & initializing this folder for our project with the npm init command that will create one package.json file. The package.json file will look like this:
You can see in the above image that there are no packages installed that we need to make JWT authentication in Express with MongoDB. So, We will install important NPM packages for it.
To Bring Authentication & Authorization In Our Application We Need To Install NPM Packages & They Are As Follows:
Now We Will Install All The Above Packages With NPM In Our Project Directory. After Installing All the Above Packages Your Package.json File Will Look Like As Follows:
Now We Have All The Packages That We Need To Bring JWT Authentication & Authorization In Our Application. So let’s start Our Project By Setting Up an App.js File.
We Will require bodyparser, express in our app.js file & use bodyParser.json() Middleware for getting requests from the body in JSON format. Then we will initialize the express application by calling the express function in the app variable.
Then we will set the route for the home page “/” and send the response as “hi” The more explanation for this route is as follows:
"/"
).Finally, we will listen to our application on PORT 8080. The Whole Above Process is shown In the Following Image:
After Running The Code With “node app.js” visit “http://localhost:8080/” & You should get “HI”.
Now We Will Make a View Folder So that we can make a Login Page where the user can log in with credentials, a Register Page where the user can register to use the services.
The Dashboard page will be shown only to the user when he logs in with credentials & has cookies with a unique JSON web token.
As You Can See In the Above Image We Have Created One Views Folder Where All The Views Will Be Stored. In the views folder, we will create three views (Pages) for login, register & dashboard.
We Will Set Ejs as the template engine in the app.js file to tell our express application that we are going to use EJS for server-side rendering.
Now We Will Set The Get Routes For The Home Page, SignIn Page & Dashboard page And Start Our Application With Nodemon as shown in the following image:
app.get("/", (req,res)=>{
res.render("register")
})
app.get("/sigin", (req,res)=>{
res.render("signIn");
})
app.get("/dashboard", (req,res)=>{
res.render("Dashboard");
})
Now If we visit the created route we have blank pages because we do not have created content for views pages. So let’s create a register form on the register page & sign-in form on the sign-in page.
Register Page:
<h1>SigIn Page</h1>
<form action="/sigin">
<input type="email" name="email" id="email" placeholder="Enter Your Email">
<input type="password" name="password" id="password" placeholder="Enter Your Password">
<input type="submit" value="submit">
</form>
In the Register Page, We Will Take the User Email, Password & Confirm Password.
SigIn Page:
<h1>SigIn Page</h1>
<form action="/sigin">
<input type="email" name="email" id="email" placeholder="Enter Your Email">
<input type="password" name="password" id="password" placeholder="Enter Your Password">
<input type="submit" value="submit">
</form>
In SigIn Page we will create email & password input
Dashboard Page:
<h1>This Is Private Page</h1>
The Output Of All the Above Three Pages Will be Shown As Follows:
Now We Will Start Bulidign Login For Our Routes. First, we will create a user in MongoDB by taking input from the register page. We will encrypt the password, check whether the password & confirm password fields are matched & save the user document in the database.
To Take The Input From Frontend Here we are using EJS we have to make a request to the backend & we can do this by creating put routes, the same as we have created get routes to render all the above pages.
To Send Data From Frontend To Backend Express Application You Have To Use Two Built In Middlewares Provided by Express:
app.use(express.json());
app.use(express.urlencoded({extended: true}))
At first, we will take input from the form & console in the backend terminal as shown in the following Image & code:
app.post("/", (req,res)=>{
const { email, password, cpassword} = req.body;
console.log(email);
res.send("User Regisistered")
})
Now We Can access other user credentials from a frontend like email & password.
Step 1: Install bcryptjs with the command npm “I npm i bcryptjs” to encrypt the password before we save it in the database.
Step 2: Require Bcrypt In Our App.js File:
const bcrypt = require("bcryptjs");
Step 3: In bcryptjs, we use mainly two methods:
Step 4: Converting post callback function into async & reassigning the original password with the hashed one as shown in the following code:
app.post("/reg", async (req,res)=>{
let { name, email, password} = req.body;
if( !name || !email || !password){
res.send("Please Enter All The Credentials")
}
let salt = await bcrypt.genSalt(10);
let hashpass = await bcrypt.hash(password, salt);
password = hashpass;
user.create({email: email, password: hashpass, name: name})
console.log(password);
res.send("User Regisistered")
})
Step 1: Create Schema With Mongoose: To save the user credentials we have to create the user schema which simply means how we want to save the data in the database. To create user schema we can simply create one userSchema.js file.
Step 2: Install Mongoose: It helps to communicate from the express app to the MongoDB database. Make sure you have installed mongoDB & mongo Shell on your PC.
Step3: Design UserShcema As Shown In Following Image & Code:
Copy UserSchema Code:
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
name:{
type: 'string',
required: true,
unique: true
},
email:{
type: 'string',
required: true,
unique: true
},
password:{
type: 'string',
required: true,
}
})
const user = mongoose.model(WebDevPro,UserSchema);
module.exports = user;
We have imported mongoose and have created one instance of mongoose with a new keyword. We have also defined what we are strong in the database & in which format. After all, we have defined the name of the model in which we have to store the document & export the user.
Step4: Import the User Model In the app.js file to perform the CRUD operations in the database. As shown in the following Image:
Step5: Connect To the DataBase: Get Your Database Name from MongoDB Compass & put it after the default URL as shown in the following code:
const dburl = "mongodb://localhost:27017/WebDevPro";
mongoose.connect(dburl)
.then(() => console.log("Database Connected Successfully"))
.catch(err => console.error("Database connection error:", err));
Step 6: Now We Are Connected To The Database. We Can Save & Create The User Information From Frontend with “user.create()” method As Shown In the Following Code:
app.post("/reg", async (req,res)=>{
let { name, email, password} = req.body;
if( !name || !email || !password){
res.send("Please Enter All The Credentials")
}
let salt = await bcrypt.genSalt(10);
let hashpass = await bcrypt.hash(password, salt);
password = hashpass;
user.create({email: email, password: hashpass, name: name})
console.log(password);
res.send("User Regisistered")
})
Step 7: Check The Post Route Is Working Or Not:
Now, we will create a user Sign-in route with the JWT token. We will first get the email & password from the request.body. If any field is missing we will send “Please Fill The Credentials”.
If all the fields are present then we will find the user from email with the finderOne method that we can use on the “user” that we defined in the user schema. If we cannot find the user in the database then we will send a “Register First” message.
If we find the user in the database, we will compare the front-end password to the database’s encrypted password with the bcrypt.compare() method. If the password does not match we will send “Invalid Credentials”
If both passwords are matched then we will create a token with secreate key that we will send as a cookie for authentication. To create cookies we will use jwt.sign() method as shown in the following code. Send it as a cookie with res.cookie().
app.post("/signin", async (req,res)=>{
let {email, password} = req.body;
if(!email || !password){
res.send("Please Fill The Credentials")
}
try{
let find = await user.findOne({email});
if(!find){
res.send("Register First")
}
let ismatch = await bcrypt.compare(password,find.password);
if(!ismatch){
res.send("Invalid Credientials")
}
const token = jwt.sign({id: find._id}, jswSecrate, {expiresIn: '1h'} );
res.cookie('jsmtoken', token, {httpOnly: true});
res.send("Login Successful")
}catch(err){
console.log(err);
}
})
We have successfully checked the user credentials & sent a cookie. Now we can use that cookie to show the specific page only to authenticated users.
To add this functionality to our application we have to create one custom middleware ( function which has access to request, response & next function ).
We will request a cookie from the front end if there is no cookie we will send a “Please Login” message or we can redirect to the login page.
If the cookie is present with a token name that we have given when creating a user we will verify the cookie with our secret key and if it verifies it successfully we will call the next function.
const is_autheticated = async (req,res, next)=>{
let check_token = await req.cookies.jsmtoken;
if(!check_token){
res.send("Please Login");
}
jwt.verify(check_token, jswSecrate, (err, user)=>{
if(err){
res.send("Please Login Again")
}
})
next();
}
Now we just have to add this middleware before the route in which we have to add the functionality shown in the following code:
app.get("/dashboard", is_autheticated , (req,res)=>{
res.render("Dashboard");
})
In this way, we can create new users with a registration form and sign with JSW cookie-based authentication.
Last Updated: August 7, 2024