JWT Authentication In Express With MongoDB

How To DO JWT Authentication In Express With MongoDB

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.

What is JWT & What Are The Advantages Of Using JWT?

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:

  1. They Are Smaller In Size Because Of JSON Format.
  2. They Are Self Contained Means They Carry All Information Within The Token Securely.
  3. They Do Not Need Server Side Processing Which Saves Our Resources.
  4. They Can Be Used For Authentication, Authorization, And Data Exchange.

Folder Structure For JWT Authentication In Express With MongoDB

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:

Package.Json File After NPM INIT

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.

Installing Important NPM Packages

To Bring Authentication & Authorization In Our Application We Need To Install NPM Packages & They Are As Follows:

  1. Express: Node Js Server For Making Server With Minimal Code.
  2. JSON Web Token (Jwt): For Authentication & Authorization.
  3. Mongoose: For Making Database Queries From Our Application To Mongodb
  4. Cookie Parser: To Parse The Cookies From Our Application To The Client Browser.
  5. Body Parser: To Parser The Data From The Client To The Backend In JSON Format.
  6. Ejs: Template Engine For Rendering HTML Pages.

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:

Package.Json File

Setting Basic App.js File

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:

  1. app.get(“/”): This defines a route for GET requests to the root URL ("/").
  2. req: Represents the request object.
  3. res: Represents the response object.
  4. res.send(“hi”): Sends a response with the text “hi” when the root URL is accessed.

Finally, we will listen to our application on PORT 8080. The Whole Above Process is shown In the Following Image:

Installing Important NPM Packages For JWT Authentication Authorization 1

After Running The Code With “node app.js” visit “http://localhost:8080/” & You should get “HI”.

Making View Folder For login, Register & DashBoard Page.

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.

image

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.

image 1

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:

JWT Authentication In Express With MongoDB - View Pages

Creating A User In MongoDB DataBase With Encryption (bcrypt.js)

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")
})
JWT Authentication In Express With MongoDB - Successfully Logged Email In Console From Frontend

Now We Can access other user credentials from a frontend like email & password.

Encrypting Password With Bcrypt

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:

  1. gensalt: Generating The Salt.
  2. hash: Hashing The Password With Generated Salt.

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")
})

Saving Hashed Password & User Credentials In MongoDB

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:

image 4

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:

image 5

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:

Creating User SignIn Route With JWT Token

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);
}
})

Showing DashBoard Page Only To Authenticated User

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");
})

Conclusion

In this way, we can create new users with a registration form and sign with JSW cookie-based authentication.


Last Updated: August 7, 2024

By JSM Hemant

About Author

Hello, Myself Hemant. I Am Web Developer & Likes To Create Awesome Projects By Using MERN, Java, Python, C++. In This Website You Will Get Cool Projects Made With Above Technologies With Full Source Code. You Can Also Follow This Website On Author Social Media:

Leave a Reply

Your email address will not be published. Required fields are marked *

Categories

Recent Posts