DEV Community

Cover image for Your API is cute, but is it secure?
Dhaval Agr'vat
Dhaval Agr'vat

Posted on

Your API is cute, but is it secure?

Your API is Cute, But Where's the Real Backend? - Part 2 🤔

In Part 1, we ran the kitchen - took orders, routed them to the right chefs, and served our hungry users.
But now it's time to secure the place.
Because a solid backend without security is like a fancy restaurant with the doors wide open and your secret sauce recipe taped to the front window.


Soo... Let Me Cook 👨🏻‍🍳 !!!


🧾 1. JWTs - Who's Allowed In?

A guy in a stained T-shirt walks through the back door claiming he's "new kitchen staff."
No apron. No ID. Just vibes 🤨.
Would you:
a) Hand him the spatula? 🍳
b) Call the manager? 📞
c) Chuck him out? 🚫

In a restaurant, identity matters. So does it in your backend.

Think of JWTs (JSON Web Tokens) as guest passes. Without one, you're not getting a seat, let alone the special menu.

🧂 How it works:

// User logs in → you give them a signed token
{
  "userId": "12345",
  "role": "admin",
  "exp": 1724102400
}

// Client sends it in every request
Authorization: Bearer <token>

// You verify it on every incoming request
Enter fullscreen mode Exit fullscreen mode

🔐 No token, no service. Go grab a reservation.


🧾 2. Validate Everything - Trust No Ingredient

An order slip comes in:
"One 🍔 burger with alert(&quot;HAH!&quot;) sauce and a DROP TABLE fries 🍟💣."
Your chef pauses. This ain't food - it's sabotage 🧨.

Never trust raw input. That's how you end up with broken dishes and food poisoning (aka bugs and exploits) 🤢.

Why I use Zod:

  • TypeScript-friendly.
  • Clear schema definitions.
  • Instant, helpful error messages.
import { z } from "zod";

const orderSchema = z.object({
  itemId: z.string().uuid(),
  quantity: z.number().min(1),
  instructions: z.string().optional(),
});

const result = orderSchema.safeParse(req.body);

if (!result.success) {
  return res.status(400).json({ error: result.error });
}
Enter fullscreen mode Exit fullscreen mode

🍅 Bad inputs don't get past the kitchen door.



🧾 3. Request Signatures - Is It Really from the Delivery Partner?

You get a phone call 📞:
"Yeah, send 20 pizzas🍕 to table 12. No, you don't know me. But trust me 🚩."

Sketchy, right?

Stripe, Razorpay, or Twilio send data to your backend. But how do you know it's actually from them?

You verify the signature:

const sig = req.headers['stripe-signature'];
const event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
Enter fullscreen mode Exit fullscreen mode

✉️ Fake orders? Not in my kitchen.


🧾 4. Rate Limiting - No One Gets to Hog the Buffet

Imagine an all-you-can-eat buffet 🍽️. Everyone's welcome - but if someone starts hogging the French fries🍟 tray and stuffing it into their bag 🛍️, you're gonna have a problem.

Rate limiting is your gentle-yet-firm waiter 👨‍🍳 who says,
"Sir, you've already had 100 dumplings 🥟. Let's give others a chance."

✅ Keeps your kitchen running smooth.
✅ Stops bad actors from overwhelming the chef.

Protect your kitchen from spammy bots and overly enthusiastic users.

import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100,
});

app.use('/api/', limiter);
Enter fullscreen mode Exit fullscreen mode

🍽️ One plate per person, please.


🧾 5. Sanitization - Clean Those Ingredients

Would you toss dirty, unwashed vegetables 🥬🥕 straight into a customer's meal?
No?
Then don't throw raw user input into your database or HTML either.

This is your sous chef 👨‍🍳 rinsing every tomato 🍅, checking for moldy spinach 🧫, and making sure no one's dropped a cockroach 🪳 in the curry 🍛 (aka <script>alert(1)</script>).

✅ Protects against XSS
✅ Keeps the dish (and your app) safe to serve

Don’t let dangerous code sneak in through user input.

  • Use xss, sanitize-html, or ORM-level sanitization.
  • Always escape stuff shown on the frontend.
  • Never directly plug user input into database queries.
import xss from 'xss';

const cleanComment = xss(req.body.comment);
Enter fullscreen mode Exit fullscreen mode

👨‍🍳 No one wants <script>alert(1)</script> in their lasagna.


🧾 6. Secure Headers - Lid on the Dish

You just made the perfect Curry 🍛.
You don't leave it sitting open near a window where flies and stray cats can jump in 🤢.
You cover it.

Secure headers are the cling film, the plastic lid, the "do not touch" sign.
They tell browsers how to treat your content safely and defensively.

✅ Deflects common exploits
✅ Gives your frontend a safety net

Add security-focused headers to protect your frontend from common attacks (XSS, clickjacking, etc.).

  • Use helmet for Express
  • Use next-secure-headers for Next.js
import helmet from 'helmet';

app.use(helmet());
Enter fullscreen mode Exit fullscreen mode

🛡️ It's the cling wrap on your freshly made ravioli.



🧾 7. Secrets & Config — Lock the Pantry

Would you shout your secret sauce recipe across the dining room while the health inspector's watching? 🤷‍♂️
Exactly.

Secrets (like API keys and DB passwords) don't belong in your codebase.

Use:

  • .env files (but keep them out of Git)
  • Secret managers (like AWS Secrets Manager, Vercel's UI, etc.)
JWT_SECRET=supersecretkey
STRIPE_KEY=sk_test_abc123
Enter fullscreen mode Exit fullscreen mode

🗝️ Would you leave your house keys taped to the door? Didn't think so.


👨‍🍳 Next Up: Observability, Logging, and Monitoring (Part 3)

The orders are flowing. The doors are locked.
But what if the stove catches fire?

In Part 3, we'll dig into:

  • 📊 Observability: see what's cooking (and what's burning)
  • 🧾 Structured logging with Winston & Pino
  • ⚠️ Monitoring, alerts, and catching bugs in real-time

Because a good chef watches every plate leave the kitchen — and knows when something's burning.


Let me know in comments if your API is now a little more secure 🍜
The kitchen's locked. Now it's time to install smoke alarms and CCTV.
See you in Part 3 🔥📊

Top comments (2)

Collapse
 
lamri_abdellahramdane_15 profile image
Lamri Abdellah Ramdane

Great analogy—locking the doors before serving dishes really drives the point home. On Windows, I’ve been using ServBay to spin up PHP, APIs, databases, and HTTPS in a click—makes testing security layers like JWTs, input validation, and headers way easier.

Collapse
 
dhaval_agrvat_6e65394a83 profile image
Dhaval Agr'vat

Glad you liked the post - ServBay sounds like a super handy setup for spinning things up quickly 🙌.