2-how-to-build-a-secure-rest-api-with-expressjs-and-jwt.html

How to Build a Secure REST API with Express.js and JWT

In today's digital landscape, building secure web applications is paramount. One of the most common architectures for web services is REST (Representational State Transfer), and when combined with Express.js and JSON Web Tokens (JWT), you can create robust and secure APIs. In this article, we'll explore how to build a secure REST API using Express.js and JWT, providing you with actionable insights and code examples to guide you along the way.

What is Express.js?

Express.js is a fast, unopinionated, and minimalist web framework for Node.js. It simplifies the process of building web applications and APIs, allowing developers to create server-side applications with ease. Express provides a robust set of features, including routing, middleware support, and easy integration with databases.

What is JWT?

JSON Web Tokens (JWT) are an open standard for securely transmitting information between parties as a JSON object. They are widely used for authentication and authorization in web applications. JWTs are compact, URL-safe, and can be verified and trusted because they are digitally signed.

Use Cases for Secure REST APIs

Before diving into the implementation, let's discuss when and why you might want to build a secure REST API:

  • User Authentication: Securely manage user sessions and restrict access to certain routes.
  • Data Protection: Ensure that sensitive data remains confidential during transmission.
  • Role-Based Access Control: Implement different access levels for users based on roles.
  • Third-Party Integrations: Allow secure access to your API for external applications.

Setting Up Your Environment

To start building your REST API, you need Node.js and npm (Node Package Manager) installed on your machine. Once you have those set up, you can create a new project:

mkdir secure-api
cd secure-api
npm init -y

Next, install the required packages:

npm install express jsonwebtoken bcryptjs body-parser dotenv
  • express: The web framework.
  • jsonwebtoken: Library to work with JWT.
  • bcryptjs: Library for hashing passwords.
  • body-parser: Middleware for parsing request bodies.
  • dotenv: For managing environment variables.

Building the API

Step 1: Setting Up Express

Create a new file named app.js and set up a basic Express server:

const express = require('express');
const bodyParser = require('body-parser');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
app.use(bodyParser.json());

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

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

Step 2: User Registration

To allow users to register, create a simple in-memory user store and a route for registration:

const users = []; // In-memory user store; in production, use a database

app.post('/register', (req, res) => {
    const { username, password } = req.body;
    const hashedPassword = bcrypt.hashSync(password, 8);

    users.push({ username, password: hashedPassword });
    res.status(201).send({ message: 'User registered successfully!' });
});

Step 3: User Authentication

Next, create a login route that generates a JWT upon successful authentication:

const jwt = require('jsonwebtoken');

app.post('/login', (req, res) => {
    const { username, password } = req.body;
    const user = users.find(u => u.username === username);

    if (!user || !bcrypt.compareSync(password, user.password)) {
        return res.status(401).send({ message: 'Invalid credentials!' });
    }

    const token = jwt.sign({ username: user.username }, process.env.JWT_SECRET, { expiresIn: '1h' });
    res.status(200).send({ auth: true, token });
});

Step 4: Middleware for Authentication

To protect your routes, create a middleware function that verifies the JWT:

function verifyToken(req, res, next) {
    const token = req.headers['x-access-token'];

    if (!token) {
        return res.status(403).send({ message: 'No token provided!' });
    }

    jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
        if (err) {
            return res.status(500).send({ message: 'Failed to authenticate token.' });
        }
        req.userId = decoded.id;
        next();
    });
}

Step 5: Protected Route Example

Now, let’s create a protected route that only authenticated users can access:

app.get('/profile', verifyToken, (req, res) => {
    res.status(200).send({ message: `Welcome, ${req.userId}!` });
});

Testing Your API

You can test your API using tools like Postman or curl.

  1. Register a User: Send a POST request to /register with a JSON body containing username and password.
  2. Login: Send a POST request to /login with the same credentials to receive a JWT.
  3. Access Protected Route: Use the JWT in the x-access-token header to access the /profile route.

Conclusion

Building a secure REST API with Express.js and JWT is a powerful approach for managing user authentication and protecting your resources. By following the steps outlined in this article, you can create a secure API that is easy to maintain and extend. Remember to consider additional security measures such as HTTPS, input validation, and rate limiting to further enhance your API's security.

With this foundation, you are well-equipped to expand your API's functionality and integrate it with front-end applications. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.