Authentication and Authorization with NodeJS Nethsara Siyum
Tags: jwt, node, javascript, backend
Published: 2023-09-13 09:10:29

Hey guyss!!

In this tutorial I am going to show you the Authentication and Authorization, how to use it and what is the different between that two.

## Authentication

Authentication is the process of verifying the identity of a user, system, or entity trying to access a resource or perform an action. It ensures that the claimed identity is legitimate and not forged.

## Authorization

These two are little bit same so we are mostly confusing with the two words, While we are verifying the identity using Authentication we are using Authorization to determine who will have the access to the Service.

For example we can have role based system, where the regular user cant edit or delete the product while Admin can. Both of them must be verify identity using the Authentication

Hope that make sense.

------------------------------------------------------

In here on I am showing you a example project that we can used to Authentication and Authorization using NodeJS.

Lets make our environment first. I hope to use NodeJS + MongoDB for this.

We will run our NodeJS Application with Express and use the MongoDB as our Database.

**.env** File

`PORT = 8000
MONGO_URI = YOUR URI TO MONGODB`

We need these **dependencies**

`    bcrypt, dotenv, express, mongoose, morgan`

---

So our **package.json** will look like this

`{
  "name": "authentication-and-authorization",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon index.js"
  },
  "keywords": [],
  "type": "module",
  "author": "SIYUM",
  "license": "ISC",
  "dependencies": {
    "bcrypt": "^5.1.1",
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "mongoose": "^7.5.1",
    "morgan": "^1.10.0"
  }
}`

---

Lets move to the **index.js**

`import express, { json } from "express";
import morgan from "morgan";
import { config } from "dotenv";
import mongoose from "mongoose";
import authRouter from "./api/auth.js";

config();

const PORT = process.env.PORT || 3000;

const app = express();

app.use(json());
app.use(morgan("dev"));

app.use("/api/v1/auth", authRouter);

mongoose
  .connect(process.env.MONGO_URI)
  .then(() => app.listen(PORT))
  .then(() => {
    () => {
      console.log(`Server is running on port ${PORT}`);
    };
  })
  .catch((err) => {
    console.error(err);
  });`


What I did here is I created our server on the Port I mentioned in the env file or 3000. Then I imported my route “_**./api/auth.js**_” for routing. In there Implemented the routing for the users authentication
Lets begin the Authentication

Here is **auth.js** I created the registration route.

`import { Router } from "express";
import { register } from "../controller/userController.js";

const authRouter = Router();

authRouter.route("/").post(register);
export default authRouter;`

Whenever We got **api/v1/auth** POST request our registration will be fired

Here is the Register Logic

`import User from "../models/User.js";
import bcrypt from "bcrypt";

export const register = async (req, res) => {
  const salt = await bcrypt.genSalt(10);
  const hasPassword = await bcrypt.hash(req.body.password, salt);

  const user = new User({ ...req.body, password: hasPassword });
  try {
    await user.save();
    res.send(user);
  } catch (err) {
    res.status(500).send(err);
  }
};`


We are creating a Model name **User.js**.

`import mongoose from "mongoose";

import { Schema } from "mongoose";

const userSchema = new Schema(
  {
    email: {
      type: String,
      required: true,
    },
    password: {
      type: String,
      required: true,
    },
    status: {
      type: Number,
      unique: true,
      default: 1,
    },
  },
  { timestamps: true }
);

const User = mongoose.model("User", userSchema);

export default User;`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulu55k9os7xl8xjiu2y8.png)



---


Lets go basic here, whenever we want to create a user from the request, we are reading his body and adding the database relevant values, such as Email and Password. We are using bcrypt to encrypt the password before it stored in the DB. This way we are making our passwords safe to store. After saving our first user it will look like this.


Now moving to login logic.

We are saving the data in the DB, but how can we access it. Lets see.

I am hoping to do like this, Whenever we get hit to **_/api/v1/login_** we will decrypt our password and verify whether this is the legitimate user. Lets gooo.

We need to install additional dependency called jsonwebtoken, and we need to add additional attribute to our .env file.

`TOKEN_SECRET = ILOVEMEDIUM`

This can be any word, you can customize it, here is the login logic

`export const login = async (req, res) => {
  try {
    const user = await User.findOne({ email: req.body.email });
    if (user) {
      const validPass = await bcrypt.compare(req.body.password, user.password);
      if (!validPass)
        return res.status(400).send("Mobile/Email or Password is wrong");

      const token = jwt.sign(
        { id: user._id, user_type_id: user.status },
        process.env.TOKEN_SECRET
      );
      res.header("auth-token", token).send({ token: token });
    }
  } catch (err) {
    if (err instanceof NotFoundError) {
      res.status(401).send(`Mobile/Email or Password is wrong`);
    } else {
      res.status(500).send("Error retrieving User");
    }
  }
};`

After we send correct password you will get return like this


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2opmu8z5533q6vji7ry0.png)



So my friends that is how you are doing the authentication and authorization. Also we can see it injected our auth-token to header


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9grpmrnrc5yrajhhxyoi.png)



## Authorization

We often used interchangeably, authentication and authorization, but those words represent fundamentally different functions.

In simple terms, authentication is the process of verifying who a user is, while authorization is the process of verifying what they have access to.

We will use middle ware to check whether **userLoggedIn** or **isUserAdmin**.

I created **authMiddleware.js** and add the code below.

`import { TOKEN_SECRET } from "../config/config";
import { verify } from "jsonwebtoken";

export function loggedIn(req, res, next) {
  let token = req.header("Authorization");
  if (!token) return res.status(401).send("Access Denied");

  try {
    if (token.startsWith("Bearer ")) {
      token = token.slice(7, token.length).trimLeft();
    }
    const verified = verify(token, TOKEN_SECRET);
    if (verified.user_type_id === 2) {
      let req_url = req.baseUrl + req.route.path;
      if (
        req_url.includes("users/:id") &&
        parseInt(req.params.id) !== verified.id
      ) {
        return res.status(401).send("Unauthorized!");
      }
    }
    req.user = verified;
    next();
  } catch (err) {
    res.status(400).send("Invalid Token");
  }
}

export async function adminOnly(req, res, next) {
  if (req.user.user_type_id === 2) {
    return res.status(401).send("Access Denied");
  }
  next();
}`

And you should add the flag to the route , index.js

`app.use("/api/v1/user", loggedIn, userRouter);`


Folder Structure

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m9toh3go3hmilu3hmnf1.png)



Thats how we are doing Authentication and Authorization in the NodeJS App. Hope you like this tutorial.

Final Code : [https://github.com/Nethsara/node-authentication---authorization](https://github.com/Nethsara/node-authentication---authorization)

Thanks for reading.