Home
About Us
Blogs

TechSteer

- Recent Posts -

How to secure your API? A Comprehensive Guide!

How to secure your API? A Comprehensive Guide!

How to secure your API. A Comprehensive Guide!

Sections

  • Introduction
  • Basics
  • A tutorial with practices on ExpressJS API
  • Common misconceptions
  • More ways to secure your API

Introduction

Are you writing a API, finished testing? Need to deploy it to production? Now you need to worry about preventing unauthorised access to the API. Fear not, I will guide you with a number of ways to tighten your API.

API security depends on the type of application you are making. Making a public api? You don't need security mechanisms. Making a public api where you set values? You need a admin only api key access. Making a subscription based API service, now you need to make a user specific api key.

How will you authenticate to the API? Some good ways to authenticate include using post requests or headers.

We will now get to basics and explanation of terms used in this article

Basics

For most APIs, there are 2 types of routes

  • Protected routes (Admin-only)
  • Public/Unprotected routes (Anyone)

- Protected routes:

You need to protect these routes behind a logic wall. These routes typically consist of database requests and edit requests which for most APIs you won't want a user to access.

- Unprotected routes:

You don't need to protect these routes, typically routes like /ping where authentication is not really required, but still safeguards like ratelimiting, user access control are required.

Above given knowledge is only for most APIs, you should use whatever you feel is the best for your use-case

The protected routes are typically protected by a API key, which you can define in your .env files. This key shouldn't be shared to anyone.

You must be asking... Enough of knowledge, show me the code. Don't worry. I will be using ExpressJS as a base here.

I will explain every part with detail so the basics aren't just over yet (hehe)

A tutorial with practices on ExpressJS API

Let's create a default express app that returns Hello World at /ping

// app.js
const express = require('express'); // Import Express 
const app = express(); // App instance
const PORT = process.env.PORT || 3000; // Port variable

// Basic health check route
app.get('/ping', (req, res) => {
  res.send('Hello World'); // Send response
}); // GET route handler

// Start server
app.listen(PORT, () => {
  console.log(`API listening on http://localhost:${PORT}`); // Startup log
}); // Begin listening on the port

Here we are using ES5 syntax, you need to change it to ES6 if you are using ES6

Here now the route is unprotected. We will keep this route as unprotected (for now)

Now let's add a protected route at /protected

Replace the /ping get route with following:

// app.js
// Parse JSON bodies for POST
app.use(express.json()); // Built-in JSON parser

// Simple health check
app.get('/ping', (req, res) => {
  res.send('Hello World'); // Plain text response
});

// API key auth middleware
function requireApiKey(req, res, next) {
  const provided =
    req.header('x-api-key') ||
    req.query.api_key ||
    (req.body && req.body.api_key); // Accept header, query, or body
  const expected = process.env.API_KEY; // Read env var
  if (!expected) {
    return res.status(500).json({ error: 'Server misconfigured: API_KEY missing' }); // Guardrail
  }
  if (provided && provided === expected) return next(); // Match -> continue 
  return res.status(401).json({ error: 'Unauthorized: invalid or missing API key' }); // 401 on fail
}

// Protected GET
app.get('/protected', requireApiKey, (req, res) => {
  res.json({ ok: true, method: 'GET', message: 'Access granted' }); // JSON reply
});

// Protected POST
app.post('/protected', requireApiKey, (req, res) => {
  res.json({ ok: true, method: 'POST', data: req.body || null }); // Echo body 
});

This is just a example. You should always use headers for sending request. They aren't logged in requests (mostly)

Congrats 🎉, now you have a protected route.

How it works?

  • Whenever a request is made to /protected (in this case I have added a post as well as get route), it calls a middleware function that will acts as a security guard demanding id which will be out environment variable API_KEY. Define a value like this in your .env
API_KEY = "asecureapikeygoeshere"
  • The function will check if the provided API key, which here can be given in 3 ways, a header X-API-KEY, a query like /protected?api_key=asecureapikeygoeshere, or a post request with a body "api_key": "yoursecurekeygoeshere"

  • If the key matches our .env variable, the request is allowed, if not a 401 (Unauthorised) error code is sent

And that's it, now you have a protected route. Let's get to some common misconceptions

Common misconceptions

-You need a rate limit on the API, many Devs do not add a rate limit to the API, allowing brute force attacks, which even when you have a DDoS Protection is still a bad idea.

Here's a code example with ratelimit:

// at top of app.js, after: const app = express();
const rateLimit = require('express-rate-limit'); // npm i express-rate-limit

// define a limiter for protected endpoints (e.g., 60 reqs/min per IP)
const protectedLimiter = rateLimit({
  windowMs: 60 * 1000,           // 1 minute window
  limit: 60,                     // allow 60 requests per IP per window 
  standardHeaders: true,         // send RateLimit-* headers 
  legacyHeaders: false,          // disable X-RateLimit-*
  message: { error: 'Rate limit exceeded. Try again later.' }, // 429 body
  statusCode: 429,               // Too Many Requests
});

And update the below routes with

// replace your protected routes with these to add the limiter
app.get('/protected', protectedLimiter, requireApiKey, (req, res) => {
  res.json({ ok: true, method: 'GET', message: 'Access granted' });
});

app.post('/protected', protectedLimiter, requireApiKey, (req, res) => {
  res.json({ ok: true, method: 'POST', data: req.body || null });
});

  • Don't use a less secure key. You can use commands like
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
openssl rand -base64 32

Or a python program like:

import secrets
key = secrets.token_urlsafe(32)  # ~256-bit entropy
print(key)

to get a secure api key

  • Don't upload the env file to a GitHub public report or even private (or any other site). The key should be strictly available to you and only you.

Moving on to more ways for security..

More ways to secure you API.

We are not going any more in this guide (for now), but if you need more deep guide, please email me at email

I will tell some good ol ways to secure your API:

  1. Hash the key while requests and compare against the hashed key to prevent request logging

  2. Use latest version of all your dependencies to ensure remaining up to date

  3. Try to see the requests coming, if you see any malicious requests, try to take action rather than seeing them try

  4. For per-user API access, you will need to check for the API key (hash the key please) in a database of users, then check if that API Key has a valid usage. Charge the user proper amount for his usage.

  5. This guide tells you to use get, post and header for sending API key but always prefer header.

  6. The comparisons used aren't timing safe in this code. If you want to tighten even that, you should look into crypto.timingSafeEqual() method

Now signing off, thank you for reading this page

Hope you have a good day and happy coding ;) 💕

UnknownVPS
October 31, 2025
Welcome to TechSteer Blog

Welcome to TechSteer Blog

Welcome to TechSteer

TechSteer is a tech blog for your tech needs

We will try our best to provide you with quality content.

A Quick rundown on the blog and its expected quality is given below:

  • Human-made blogs. We try to keep quality high so all blogs will be human written.
  • Giving you new content to explore
  • All posts will follow a certain format that may change overtime, but all posts will still be standardized
  • Fast: We try to use fast servers to enhance your experience
  • This blog will always remain free for any post

Why TechSteer

TechSteer is a quality blog brought by UnknownVPS. Most of our products are free for public use and most of them are adfree. We intend to continue providing these services but the blog may not continue to be adfree.

Unlike other blogs which are mostly using AI Generated content for views, we will try our best to give you the best.

The first blog post is short but there is always more to come.

UnknownVPS
October 28, 2025