How to add authorization in Node.js API
If you are a beginner developer you might know that there are multiple types of validations. As a website developer if you are using React.js or any other frontend technologies you would validate data before sending it to the server to make API request. That is alright since you are restricting user to only send data in a structure you want. But what if any person makes a API request directly without using your website’s/App frontend? They are send data that might be harmful for our backend and it might crash our server if things are not handled well. It can also be possible that an anonymous user try to access APIs that only admin should be accessing. In this tutorial we will be learning to add authorization on our Node.js server to entertain only the authorized user request.
Authorization
Authorization is the function of specifying access rights/privileges to resources, which is related to general information security and computer security, and to access control in particular.
Getting Started
To get started we will create the basic structure for our backend that is on Node.js and Express.js. If you are a beginner or want to follow the tutorial you should checkout my article where I explained the node.js application structure. (link)
First, we will clone the project from https://github.com/MuqtadirBillah/node-express-basic-structure. It contains the basic structure that will be followed in this tutorial.
Once you clone that repo the project structure will look like this
In this project we have the very basic authentication added to it. We will first improve it then, we will add new routes and add authorization to them.
Add Authentication
We will be adding two new packages to our project i.e. “bcryptjs” and “jsonwebtoken”. To install those packages you need to execute the below command.
npm install bcryptjs jsonwebtoken
Now before starting you need to start mongodb local server. Then, just execute the below command on terminal to start our server.
npm start
Now once the server is started, we will first improve our registration logic. To make changes in it you need to access authController that can be found in controllers folder.
I will be changing only the password field in register function. I will be using bcrypt to hash it and then store in database.
To use bcryptjs we need to first import it at the top
const bcrypt = require('bcryptjs');
Next, we need to hash it. I will be hashing with auto salt. You can read the docs at bcryptjs.
let hashedPassword = bcrypt.hashSync(req.body.password, 10);
And then I will replace req.body.password to hashedPassword so that we will only add hashed password in our database.
const user = await new User({
email: req.body.email,
password: hashedPassword,
username: req.body.username,
creation_date: moment().format("MMMM Do YYYY, h:mm:ss a")
})
Now once the registration logic is bit improved, let’s work on our login logic.
Now in logic function we will be comparing hashed password to entered password by a bcrypt function.
if(bcrypt.compareSync(req.body.password, docs[0].password)){
res.status(200).json({ status: "success" })
}
else{
res.send("Invalid Credentials!");
}
Now once the password is matched we will creating a jwt (json web token) with basic details that will be used and checked when making a API request. (You can add more details in it but currently I am only saving username and email to it).
Now here I will be signing a jwt and sending the token with API response. You can read the official documentation at JWT. Make sure to import it at the top.
if(bcrypt.compareSync(req.body.password, docs[0].password)){
let token = jwt.sign({ foo: 'bar' }, "f0af17449a83681de22db7ce16672f16f37131bec0022371d4ace5d1854301e0");
res.status(200).json({ status: "success", token: token })
}
else{
res.send("Invalid Credentials!");
}
Now, Let’s test if everything is working as expected. To test it our we will be using postman.
Testing Registration API
If you are getting response with a message “added!”, it means your user is getting registered. To confirm it you can view it in your database. I am currently using Mongodb Compase for it.
Here I can see the registered user info.
Next, I will be testing”Login” API. We will perform it in Postman as well, and will change on url.
Now if you login with correct credentials you will get status and jwt.
Let’s copy the jwt as we will be using it later.
Creating a Authorized User Route
Earlier, we were using Login and Register API for authentication, but it does not have any authorization or restrictions. We were able to use it without any permission and prior identity.
Now we will be creating a route that will only be accessible to logged in user only. To do it so, we will be adding a new controller first.
I will be creating the controller named as “userController” and will be making a function called getJoke() that will get jokes from third party API. In the end I will export that function so that we can access in our router file.
Now I will create userRoutes in routes folder.
const express = require("express");
const userController = require("../controllers/userController")
const userRouter = express.Router();
userRouter.route("/joke").get(userController.getJoke);
module.exports = userRouter;
Next I will import it in index.js in routes folder.
const { Router: expressRouter } = require("express");
const router = expressRouter();
// auth routes
const authRouter = require("./authRoutes");
router.use("/auth", authRouter);
// user routes
const userRouter = require("./userRoutes");
router.use("/user", userRouter);
module.exports = router;
Now, let’s test the API.
Here we are getting the response.
Adding Authorization
Now I want only login user with correct jwt to access this API. To do so I will be creating a middleware called verify.js in a new folder called “middlewares”.
const jwt = require("jsonwebtoken")
const { jwt_key } = require("../config/db.config")
const { handleResponseWithStatus } = require("../helper/utils");
const verifyToken = (req, res, next)=>{
const token = req.headers.token
if(token!=undefined){
jwt.verify(token, jwt_key, function(err, decoded) {
if(err){
console.log(err)
res.send({ status: "error", error: 'Unauthorized User!' });
}
else{
if(decoded!=undefined){
console.log(decoded)
next();
}
else{
res.send({ status: "error", error: 'Unauthorized User!' });
}
}
});
}
else{
res.send({ status: "error", error: 'Unauthorized User!' });
}
}
module.exports = verifyToken;
You can view that file at link. I will import this function in middlewares index.js as “isAuthenticated”.
module.exports = {
isAuthenticated: require("./verify"),
}
Next, I will be add it as middleware in routes, before accessing the API function i.e. getJoke. It will be added in userRoutes.js
const express = require("express");
const userController = require("../controllers/userController")
const userRouter = express.Router();
const { isAuthenticated } = require("../middlewares");
userRouter.route("/joke").get(isAuthenticated, userController.getJoke);
module.exports = userRouter;
Now, we will test if we can access “http://localhost:5000/api/user/joke” API without any permissions.
Currently if I try to access it. It gives an error that “Unauthorized User”.
Now to make it work, we need to verify ourself. To do so, we will be sending JWT in header so that our middleware can verify that the user accessing is authorized.
I am adding a key name “token” in our postman header section and will put the value that we were getting while login as JWT.
Now if we try to make a request with JWT token on getJoke API we are able to access it.
In this way, we can add authorizations on different route. You can also change logics of middleware depending on your requirements.
GitHub Repo for this article: https://github.com/MuqtadirBillah/node-express-basic-structure.git
Now you know how to add authorization in Node.js and Express.js APIs.
Follow me for more interesting tips and tricks at Musab Abbasi — Medium
You can also find me on LinkedIn and Github