In this tutorial, we will build a secure Node.js API that allows us to manage users, roles, and tasks using JWT authentication.
JWT (JSON Web Token) is a way to securely transmit information between parties as a JSON object. It is commonly used for authentication and information exchange between servers and clients. In this tutorial, we will utilize JWT for authentication purposes in our Node.js API.
Step 1: Setting up the project
To get started, let’s create a new Node.js project using npm. Open your terminal and run the following commands:
mkdir secure-nodejs-api
cd secure-nodejs-api
npm init -y
Next, install the necessary packages for our project:
npm install express body-parser bcrypt jsonwebtoken mongoose
Step 2: Setting up the database
We will be using MongoDB for our database. If you don’t have MongoDB installed on your machine, you can follow the instructions on their website to install it.
Next, we need to connect our Node.js application to the MongoDB database. Create a new file called db.js
and add the following code:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/secure_nodejs_api', {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
Step 3: Setting up the models
Next, we will create the models for users, roles, and tasks. Create a new directory called models
and create three files: user.js
, role.js
, and task.js
.
In user.js
, add the following code:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: String,
email: String,
password: String
});
const User = mongoose.model('User', userSchema);
module.exports = User;
In role.js
, add the following code:
const mongoose = require('mongoose');
const roleSchema = new mongoose.Schema({
name: String,
permissions: [String]
});
const Role = mongoose.model('Role', roleSchema);
module.exports = Role;
In task.js
, add the following code:
const mongoose = require('mongoose');
const taskSchema = new mongoose.Schema({
title: String,
description: String,
assignedTo: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
const Task = mongoose.model('Task', taskSchema);
module.exports = Task;
Step 4: Setting up the routes
Now, let’s create the routes for managing users, roles, and tasks. Create a new directory called routes
and create three files: users.js
, roles.js
, and tasks.js
.
In users.js
, add the following code:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
// Get all users
});
router.post('/', (req, res) => {
// Create a new user
});
router.get('/:id', (req, res) => {
// Get a user by ID
});
router.put('/:id', (req, res) => {
// Update a user by ID
});
router.delete('/:id', (req, res) => {
// Delete a user by ID
});
module.exports = router;
In roles.js
, add the following code:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
// Get all roles
});
router.post('/', (req, res) => {
// Create a new role
});
router.get('/:id', (req, res) => {
// Get a role by ID
});
router.put('/:id', (req, res) => {
// Update a role by ID
});
router.delete('/:id', (req, res) => {
// Delete a role by ID
});
module.exports = router;
In tasks.js
, add the following code:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
// Get all tasks
});
router.post('/', (req, res) => {
// Create a new task
});
router.get('/:id', (req, res) => {
// Get a task by ID
});
router.put('/:id', (req, res) => {
// Update a task by ID
});
router.delete('/:id', (req, res) => {
// Delete a task by ID
});
module.exports = router;
Step 5: Implementing JWT authentication
Next, we will implement JWT authentication for our API. Create a new file called auth.js
and add the following code:
const jwt = require('jsonwebtoken');
function generateToken(user) {
return jwt.sign({
id: user._id,
username: user.username,
email: user.email
}, 'secret', { expiresIn: '1h' });
}
function verifyToken(req, res, next) {
const token = req.headers.authorization;
if (!token) {
res.status(403).json({ message: 'No token provided' });
}
jwt.verify(token, 'secret', (err, decoded) => {
if (err) {
res.status(403).json({ message: 'Failed to authenticate token' });
} else {
req.user = decoded;
next();
}
});
}
module.exports = {
generateToken,
verifyToken
};
Step 6: Securing the routes
Finally, let’s secure our routes using the JWT authentication middleware. In each of the route files (users.js
, roles.js
, tasks.js
), require the auth.js
file and add the verifyToken
middleware to the routes that need authentication.
For example, in users.js
, you can add the following code to secure the routes:
const express = require('express');
const router = express.Router();
const auth = require('../auth');
router.get('/', auth.verifyToken, (req, res) => {
// Get all users
});
router.post('/', auth.verifyToken, (req, res) => {
// Create a new user
});
// Add authentication to other routes as needed
module.exports = router;
Step 7: Testing the API
Now that we have implemented the JWT authentication and secured our routes, we can test the API using tools like Postman. Make sure to have an instance of MongoDB running before testing the API.
To test the API, send requests to the endpoints we have created (e.g., /users
, /roles
, /tasks
) with valid JWT tokens in the authorization header. You can use the generateToken
function from auth.js
to generate a token for testing purposes.
Conclusion
In this tutorial, we have built a secure Node.js API that allows us to manage users, roles, and tasks using JWT authentication. We have set up the project, connected to a MongoDB database, defined models, created routes, implemented JWT authentication, and secured the routes. By following this tutorial, you have learned how to build a secure API using Node.js and JWT authentication. Happy coding! 🚀🔐