Skip to main content
Node.js APIs Tutorial
CHAPTER 15 Beginner

Building Secure APIs

Updated: May 14, 2026
30 min read

# CHAPTER 15

Building Secure APIs

1. Introduction

A beautifully written API that queries a database efficiently is worthless if a malicious script can crash it in 10 seconds. Because APIs are inherently public-facing (they sit on the open internet waiting for requests), they are under constant attack from bots, scrapers, and hackers. Node.js applications are particularly vulnerable to Denial of Service (DoS) attacks and brute-force attempts. In this chapter, we will implement industry-standard security packages to armor our Express backend.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Mitigate Denial of Service (DoS) attacks using Rate Limiting.
  • Secure HTTP headers automatically using Helmet.
  • Protect your API from Cross-Origin Resource Sharing (CORS) exploits.
  • Prevent NoSQL Injection attacks.

3. Beginner-Friendly Explanation

Imagine your API is a famous bakery.
  • Rate Limiting: A malicious rival sends 10,000 robots to stand in line and order one cookie each. Real customers cannot get in. The bakery crashes. Rate limiting sets a rule: "Only 100 cookies per person, per hour." The robots are banned.
  • Helmet: The bakery's windows are currently transparent. Thieves can look inside and see exactly what brand of cash register you use (which helps them plan a robbery). Helmet puts up tinted windows, hiding your server's technical details.
  • CORS: Someone builds a fake bakery next door that secretly pipes orders into your kitchen without permission. CORS is a VIP list at the door that ensures orders are ONLY accepted from your official website.

4. Step 1: Rate Limiting

If a hacker wants to guess a user's password, they will write a script to send 5,000 login requests per minute. We stop this using express-rate-limit.

Install: npm install express-rate-limit

In app.js:

javascript
1234567891011121314
const rateLimit = require('express-rate-limit');

// Define the rule
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100, // Limit each IP to 100 requests per windowMs
    message: "Too many requests from this IP, please try again after 15 minutes"
});

// Apply globally to all requests
app.use(limiter);

// Or, apply strictly to the login route to prevent brute-force
// app.use('/api/login', loginLimiter);

5. Step 2: Securing HTTP Headers (Helmet)

By default, Express sends a header that says X-Powered-By: Express. Hackers use bots to scan the internet for servers broadcasting this header, and then attack them with known Express vulnerabilities. helmet strips this header and adds 14 other critical security headers automatically.

Install: npm install helmet

In app.js:

javascript
1234
const helmet = require('helmet');

// Run this at the very top of your middleware stack
app.use(helmet());

*That single line of code fixes dozens of subtle security vulnerabilities.*

6. Step 3: CORS Protection

Cross-Origin Resource Sharing (CORS) is a browser security mechanism. If your API is hosted at api.myapp.com, and a hacker hosts a website at evil.com, the hacker's JavaScript might try to make a fetch request to your API to steal data. By default, browsers block this. But to allow your *own* frontend (www.myapp.com) to access the API, you must configure the CORS middleware.

Install: npm install cors

In app.js:

javascript
123456789
const cors = require('cors');

// Allow ONLY your official frontend to communicate with the API
const corsOptions = {
    origin: 'https://www.myofficialwebsite.com',
    optionsSuccessStatus: 200
};

app.use(cors(corsOptions));

7. Step 4: NoSQL Injection Prevention (Data Sanitization)

If you use MongoDB, you are immune to traditional SQL Injection, but vulnerable to NoSQL Injection. A hacker can pass a MongoDB operator (like $gt for "greater than") inside the login password field to bypass authentication.

Install: npm install express-mongo-sanitize

In app.js:

javascript
12345
const mongoSanitize = require('express-mongo-sanitize');

// This automatically intercepts req.body, req.query, and req.params,
// and completely strips out any prohibited MongoDB operators (like $)
app.use(mongoSanitize());

8. Backend Workflow: The Complete Security Stack

A production-ready app.js file should always look like this at the top:
javascript
1234567891011121314151617181920
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const mongoSanitize = require('express-mongo-sanitize');

const app = express();

// 1. Security Headers
app.use(helmet());
// 2. CORS
app.use(cors({ origin: 'https://mysite.com' }));
// 3. Rate Limiting
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));
// 4. Body Parser
app.use(express.json());
// 5. Data Sanitization (Must be AFTER body parser)
app.use(mongoSanitize());

// Routes go here...

9. Best Practices

  • Never Commit .env Files: The biggest security breach in Node.js history is developers accidentally uploading their .env files to public GitHub repositories. Bots scrape GitHub 24/7. If they find your database password or AWS keys, your infrastructure will be hijacked and deleted in seconds. ALWAYS ensure .env is inside your .gitignore file.

10. Common Mistakes

  • Applying CORS blindly: Beginners often get a red "CORS Error" in their frontend console, panic, and install app.use(cors()) with no options. This puts a wildcard * on the API, meaning *any website on earth* is now legally allowed to make requests to your API and steal data. Always restrict origin.

11. Exercises

  1. 1. Explain how a Brute Force attack works against a /login endpoint, and how express-rate-limit mitigates it.

12. Coding Challenges

  • Challenge: Configure a specialized Rate Limiter meant only for password resets. It should only allow 3 requests per IP address every 1 hour. Apply it to a mock POST route /api/forgot-password.

13. MCQs with Answers

Question 1

What is the primary function of the helmet package in an Express application?

Question 2

Why do developers implement the express-mongo-sanitize middleware in a Mongoose/MongoDB application?

14. Interview Questions

  • Q: What is CORS, and why is it a crucial security feature enforced by web browsers? How do you configure a Node.js API to handle it securely?
  • Q: Walk me through your standard security middleware stack in an app.js file. What packages do you use, and in what specific order do you place them?

15. FAQs

Q: Can rate limiting be bypassed by a hacker? A: Yes. express-rate-limit tracks IP addresses. If a hacker uses a botnet (10,000 infected computers with 10,000 different IP addresses), the rate limiter won't work. For enterprise security, you must put your API behind a professional Web Application Firewall (WAF) like Cloudflare.

16. Summary

In Chapter 15, we transformed our API from a vulnerable target into a digital fortress. By implementing a standardized security stack of middleware, we shielded our server from the most common web exploits. Helmet obscured our technical footprint, CORS restricted unauthorized domains, Express-Rate-Limit neutralized brute-force scripts, and Mongo-Sanitize eliminated NoSQL injection vectors.

17. Next Chapter Recommendation

Your API is secure, but does it actually work? Manual testing is tedious. Proceed to Chapter 16: API Testing with Postman.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·