17.2. Authentication and Authorization in NodeJS APIs: Authorization with Roles and Permissions
When building robust and secure APIs in NodeJS, authentication and authorization are critical aspects that ensure data security and integrity. Authentication is the process of verifying the identity of the user, while authorization is the process of verifying the permissions of the authenticated user. In this chapter, we'll focus on authorization with roles and permissions.
Understanding Roles and Permissions
In an application, different users can have different levels of access. For example, in a project management system, a user could be an 'Administrator', 'Manager' or 'Contributor'. Each of these roles can have different permissions. An 'Administrator' can be allowed to create, read, update and delete any project, while a 'Manager' can only create, read and update projects but not delete them. A 'Contributor' can only read projects. These are the roles and permissions.
Implementing Authorization with Roles and Permissions in NodeJS
To implement authorization with roles and permissions in NodeJS, we first need to create a user model that includes the user's role. Next, we need to create a middleware role that checks the user's role and grants or denies access based on that role.
1. Creating the User Model
We can use Mongoose, a popular ODM (Object Data Modeling) for MongoDB, to create our user model. Here is an example of what the user model might look like:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: String,
email: String,
password: String,
role: {
type: String,
enum: ['Admin', 'Manager', 'Contributor'],
default: 'Contributor'
}
});
module.exports = mongoose.model('User', UserSchema);
2. Creating the Middleware Function
Next, we need to create a middleware function that checks the user's role. We can do this using JWT (JSON Web Token), an access token standard that allows authentication between two parties. When a user authenticates, a JWT token is generated and sent to the user. This token contains information about the user, including their role. Here is an example of what the middleware function might look like:
const jwt = require('jsonwebtoken');
function authRole(role) {
return (req, res, next) => {
const token = req.header('auth-token');
if (!token) return res.status(401).send('Access Denied');
try {
const verified = jwt.verify(token, process.env.TOKEN_SECRET);
if (verified.role !== role) return res.status(403).send('Forbidden');
req.user = verified;
next();
} catch (err) {
res.status(400).send('Invalid Token');
}
};
}
module.exports = authRole;
With this middleware function, we can protect our routes based on the user's role. For example, we can protect the project delete path so that only 'Admin' users can access it:
const express = require('express');
const router = express.Router();
const authRole = require('../middleware/authRole');
router.delete('/project/:id', authRole('Admin'), (req, res) => {
// Delete project
});
In summary, authorization with roles and permissions is an essential part of creating secure APIs in NodeJS. It allows you to control access to different parts of your application based on the user's role. Implementing this correctly can help prevent unauthorized access and protect your application's data.