Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
What is JSON Web Token (JWT)?
3.
What is Authentication?
4.
What is Authorization?
5.
Project Setup
6.
Creating a Server and Connecting Database
6.1.
index.js
6.2.
conn.js
6.3.
config.env
7.
Creating Models and Routes
7.1.
userModel.js
8.
Adding Route Functionality and Generating JWT Tokens
8.1.
userRoute.js
8.2.
index.js
9.
Developing Middleware for User Authentication
10.
Frequently Asked Questions
10.1.
Why do we need APIs?
10.2.
What is an API?
10.3.
What are the benefits of using Express?
11.
Conclusion
Last Updated: Mar 27, 2024
Medium

Authentication and Authorization in Express

Introduction

Express is used by thousands of developers worldwide to create I/O-intensive web applications such as video streaming sites, single-page applications, online chat applications, and other web apps. Express is a Node.js based back-end web application framework that was distributed as free and open-source software under the MIT License.

Authentication and Authorization in Express

You will learn how to create a security layer while accessing various routes within an Express web application by following this tutorial on Express authentication with JWT. Before covering its implementation within an Express application, we will first go over the fundamentals of JWT (JSON Web Token).

What is JSON Web Token (JWT)?

JSON Web Token (JWT) is a standard that offers a concise and self-contained method for securely exchanging information as a JSON object between parties. The tokens' small size makes them easy to send through URL, POST parameter, or HTTP header. A JWT's information is digitally signed with a secret or public/private key pair. JWTs can be signed using either a private key or a public/private key pair.

JWTs are mostly used to authenticate users. When a user signs in to a program, the program assigns JWT to that user. The user's subsequent requests will include the given JWT. This token informs the server about the routes, services, and resources that the user is permitted to use. An example of a JWT token is given below:

eyJhbGciOiJIUzI1NiI5cCI6IkpXVCJ9.ey1c2VySWQiOiI2MTU0OWIwMTIwMWUyZjMzZWE3NmFkZjYiLCJlbTQ1MkBnbWFpbC5jb20iLCJpYXQiOjE2MzI5MzQ2NTgsDI1OH0._oHr3REme2pjDDdRliArAeVG_HuimbuTw8HI7uc

JSON Web Token

What is Authentication?

Identifying users through the acquisition of credentials like tokens, passwords, and email addresses is the process of authentication. The credentials given are contrasted with those of the registered user, which are kept on the local computer system's file system or in any databases. The authentication process is finished, and the user is given access to the resources if the provided credentials correspond to the information in the database.

What is Authorization?

Authorization comes after authentication. For all authorizations, a system for authentication is necessary. Giving people access to resources on systems or websites is the process at hand. We will give logged-in users access to the user information on this blog. If the user is not logged in, they will not be able to access the data.

Twitter and Facebook are two outstanding examples of authorization in social media. Without an account, you cannot access social networking features. Subscription-based content is another sort of authorization; you can authenticate by signing into the website, but you can't access the content until you subscribe.

Project Setup

Make a folder called “nodeapi” anywhere on your local computer and open it with vs-code. Start the node package manager by opening the vs-code terminal and typing: 

npm init -y


The above command will generate a package.json file containing all of the dependencies that will be used in this project. 

Now we'll download all of the necessary packages and type them into the terminal.

npm install express dotenv jsonwebtoken mongoose bcryptjs

 

You will now have files and folders, as shown below.

Initial Folder Structure

Creating a Server and Connecting Database

Create a folder called config and a file called index.js. Construct two files in the configuration folder: conn.js for the database connection and config.env for the environment variable declaration. Use the code below to fill in the blanks. Enter the code listed below into the relevant files.

index.js

const express = require("express");
const dotenv = require("dotenv");
dotenv.config({ path: "./config/config.env" });

//Creating an express app
const app = express();
app.use(express.json());

app.listen(process.env.PORT, () => {
    console.log(`Server is listening at ${process.env.PORT}`);
});

 

Before invoking any additional scripts that depend on environment variables, if you're using dotenv, make sure to configure it in your index.js file.

conn.js

const mongoose = require("mongoose");

mongoose
    .connect(process.env.URI, {
        useNewUrlParser: true,
        useUnifiedTopology: true,
    })
    .then((data) => {
        console.log(`Database is now connected to ${data.connection.host}`);
    });

 

This code is used in a Node.js application to create a connection to a MongoDB database using the Mongoose module.

config.env

URI= 'mongodb+srv://harry2002:brown@nodeapi.ulxmv.mongodb.net/authdatabase’
PORT = 5000

 

The config.env file contains the MongoDB connection URI and the Port at which the server runs.

Creating Models and Routes

A JSON document called a model shows how your data is set up in a Mongo-DB database. To create a model, we'll utilize the Mongoose schema. Algorithms for routing frequently need two arguments. The callback function, which describes what this route would do in response to a client request, comes after the route.

We'll create two folders called routes and models in the next step. Create two files: userRoute.js in the routes folder and userModel.js in the models folder. After creating the necessary files, enter the following code into them.

userModel.js

const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
 email: {
        type: String,
        required: true,
        unique: true
    },
    name: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true,
        unique: true
    },
    token: {
        type: String
    },
});

//Creating models
const userModel = mongoose.model("user", userSchema);
module.exports = userModel;

Adding Route Functionality and Generating JWT Tokens

The callback function in routing takes three arguments: the request, the response, and the next function. Use the next parameter only if necessary; it is optional. Now, modify the following code files.

userRoute.js

const express = require("express");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const SECRET_KEY = HARRYLOVESBROWNDOGS;
//Creating express router
const router = express.Router();
const userModel = require("../models/userModel");

//Creating register route
router.post("/register", async (req, res) => {
    try {
        const { name, email, password } = req.body;
        if (!name || !email || !password) {
            return res.json({ message: "Details cannot be left empty" });
        }

        //Check if the user already exist or not
        const userExist = await userModel.findOne({ email: req.body.email });
        if (userExist) {
            return res.json({
                message: "For the given email, user already exists",
            });
        }
        
        //Hash the password
        const salt = await bcrypt.genSalt(10);
        const hashPassword = await bcrypt.hash(req.body.password, salt);
        req.body.password = hashPassword;
        const user = new userModel(req.body);
        await user.save();
        const token = await jwt.sign({ id: user._id }, SECRET_KEY
        });
        return res
            .cookie({ token: token })
            .json({
                success: true,
                message: "User registered successfully",
                data: user,
            });
    } catch (error) {
        return res.json({ error: error });
    }
});

//Creating login routes
route.post("/login", async (req, res) => {
    try {
        const { email, password } = req.body;
     
        if (!email || !password) {
            return res.json({ message: "Details cannot be left empty" });
        }
        //Check if the user already exist or not
        const userExist = await userModel.findOne({ email: req.body.email });
        if (!userExist) {
            return res.json({ message: "Invalid credentials" });
        }
        //Checking password match
        const isPasswordMatched = await bcrypt.compare(
            password,
            userExist.password
        );
        if (!isPasswordMatched) {
            return res.json({ message: "Invalid credentials for password" });
        }
        const token = await jwt.sign(
            { id: userExist._id }, SECRET_KEY
        );
        return res
            .cookie({ token: token })
            .json({ success: true, message: "LoggedIn Successfully" });
    } catch (error) {
        return res.json({ error: error });
    }
});

//Creating user routes to fetch users data
route.get("/user", async (req, res) => {
    try {
        const user = await userModel.find();
        if (!user) {
            return res.json({ message: "No user found" });
        }
        return res.json({ user: user });
    } catch (error) {
        return res.json({ error: error });
    }
});

module.exports = route;

index.js

const express = require("express");
const dotenv = require("dotenv");
dotenv.config({ path: "./config/config.env" });
require("./config/conn");

//Creating an app from express
const app = express();
const route = require("./routes/userRoute");

//Using express.json to get request of json data
app.use(express.json());
//Using routes
app.use("/api", route);

app.listen(process.env.PORT, () => {
    console.log(`Server is listening at ${process.env.PORT}`);
});

Developing Middleware for User Authentication

Middleware is a function in the request-response cycle that has access to the request, response object, and next function. The "next" function is called when the function has completed running. The code below should be placed in a file called auth.js that you create in the middleware folder.

const userModel = require("../models/userModel");
const jwt = require("jsonwebtoken");
const isAuthenticated = async (req, res, next) => {
    try {
        const { token } = req.cookies;
        if (!token) {
            return next("Please login to access the data");
        }
        const verify = await jwt.verify(token, process.env.SECRET_KEY);
        req.user = await userModel.findById(verify.id);
        next();
    } catch (error) {
        return next(error);
    }
};

module.exports = isAuthenticated;

 

Install the cookie-parser library to customize the cookieParser in your app. cookieParser allows you to access the token saved in the cookie.

npm install cookie-parser

 

You should now have a cookie parser installed. Modify the index.js file and add middleware to the "/user" route to configure your project. The isAuthenticated middleware must be inserted between the request and response of the “/user” route as shown below:

route.get("/user", isAuthenticated, async (req, res) => {
//The code given previously
}

 

Finally, once your code is complete and the server is running, go to Postman and test it.

Frequently Asked Questions

Why do we need APIs?

APIs enable developers to create applications that can interact with other apps, services, or data sources. This can improve efficiency and enable more complex and powerful apps by streamlining the development process.

What is an API?

An API, or Application Programming Interface, is a set of protocols and tools for developing software applications. APIs specify how software components should interact and communicate with one another, allowing various programs to communicate and share data.

What are the benefits of using Express?

Express is easy to set up and personalize. It comes with a slew of middleware modules that makes authentication and authorization in Express much easier. It allows you to build application routes using URLs and HTTP methods.

Conclusion

Express.js application security depends heavily on authentication and authorization. In this tutorial, we discussed concepts of authentication and authorization in Express, JWT, and a complete working code example. To better understand the topic, you can refer to Introduction to ExpressSetting up Express.js, and Authenticating Users With Node ExpressJS and Passport.js.

For more information, refer to our Guided Path on CodeStudio to upskill yourself in PythonData Structures and AlgorithmsCompetitive ProgrammingSystem Design, and many more! 

Head over to our practice platform, CodeStudio, to practice top problems, attempt mock tests, read interview experiences and interview bundles, follow guided paths for placement preparations, and much more!

Live masterclass