This content originally appeared on DEV Community and was authored by Haque.
Introduction
Role-Based Authentication (RBA) is a method to control access based on user roles (e.g., Admin, User, Manager). This tutorial will guide you through implementing RBA in a Node.js application using Express.js and MongoDB.
Prerequisites
Before we start, ensure you have the following:
- Node.js installed on your system
- MongoDB set up and running
- Basic knowledge of Express.js and JWT (JSON Web Tokens)
- A tool like Postman or cURL for API testing
Steps to Implement Role-Based Authentication
1. Initialize the Project
First, create a new project folder and initialize a Node.js project.
mkdir role-based-auth
cd role-based-auth
npm init -y
This creates a package.json
file for managing dependencies.
Now, install the required packages:
npm install express mongoose bcryptjs jsonwebtoken dotenv cors express-rate-limit https
express
: Web framework for Node.js
mongoose
: ODM (Object Data Modeling) library for MongoDB
bcryptjs
: For hashing passwords securely
jsonwebtoken
: To generate and verify authentication tokens
dotenv
: For managing environment variables
cors
: To enable Cross-Origin Resource Sharing
express-rate-limit
: To prevent API abuse
https
: For secure HTTPS implementation
2. Set Up the Server
Create server.js
and configure the Express server:
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const fs = require('fs');
const https = require('https');
const rateLimit = require('express-rate-limit');
const authRoutes = require('./routes/authRoutes');
const protectedRoutes = require('./routes/protectedRoutes');
const app = express();
app.use(express.json());
app.use('/api/auth', authRoutes);
app.use('/api/protected', protectedRoutes);
// Rate Limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per window
message: 'Too many requests, please try again later.'
});
app.use(limiter);
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => console.log("MongoDB Connected"))
.catch(err => console.error(err));
const httpsOptions = {
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem')
};
https.createServer(httpsOptions, app).listen(5000, () => console.log('Server running on port 5000 (HTTPS)'));
3. Implement Refresh Tokens
Modify routes/authRoutes.js
to include refresh tokens:
const jwt = require('jsonwebtoken');
const refreshTokens = [];
// Generate Access Token
const generateAccessToken = (user) => {
return jwt.sign({ id: user._id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '15m' });
};
// Generate Refresh Token
const generateRefreshToken = (user) => {
const refreshToken = jwt.sign({ id: user._id }, process.env.REFRESH_SECRET);
refreshTokens.push(refreshToken);
return refreshToken;
};
// Refresh Token Route
router.post('/refresh', (req, res) => {
const { token } = req.body;
if (!token || !refreshTokens.includes(token)) {
return res.status(403).json({ message: 'Access denied' });
}
jwt.verify(token, process.env.REFRESH_SECRET, (err, user) => {
if (err) return res.status(403).json({ message: 'Invalid refresh token' });
const accessToken = generateAccessToken(user);
res.json({ accessToken });
});
});
4. Implement Role Management
Modify routes/authRoutes.js
to allow admin to change user roles:
const { authenticate, authorize } = require('../middleware/authMiddleware');
// Change User Role (Admin Only)
router.put('/change-role/:id', authenticate, authorize(['admin']), async (req, res) => {
try {
const { role } = req.body;
const user = await User.findByIdAndUpdate(req.params.id, { role }, { new: true });
res.json({ message: 'User role updated', user });
} catch (err) {
res.status(500).json({ error: 'Server error' });
}
});
5. Secure the API with HTTPS & Rate Limiting
- HTTPS: Uses SSL/TLS encryption
- Rate Limiting: Limits requests per IP
6. Test the API
Start the server:
node server.js
Use Postman or cURL to test:
- Register a user: POST /api/auth/register
- Login to receive a token: POST /api/auth/login
- Get a new access token: POST /api/auth/refresh
- Change user role (Admin only): PUT /api/auth/change-role/:id
- Access protected routes:
- GET /api/protected/admin (Admin only)
- GET /api/protected/user (User and Admin)
Conclusion
You have successfully implemented Role-Based Authentication in Node.js Express with MongoDB.
Key Features:
Refresh tokens for session management
Dynamic role management
API security with HTTPS & rate limiting
This content originally appeared on DEV Community and was authored by Haque.