DEV Community

Cover image for 🔐 From 0 Production-Grade Security
Kira Zenith
Kira Zenith

Posted on

🔐 From 0 Production-Grade Security

“If it works on localhost, hackers say thank you.”

Let’s go from completely insecure → production-ready security in simple steps.


0. The Reality Check

  • Every app is vulnerable by default
  • Security is NOT a feature → it’s a layered system
  • Goal: make hacking too expensive & annoying

1. Basic Hygiene (Don’t Be an Easy Target)

  • Use HTTPS only (no excuses)
// Express.js
app.use((req, res, next) => {
  if (req.protocol === 'http') {
    return res.redirect(`https://${req.headers.host}${req.url}`);
  }
  next();
});
Enter fullscreen mode Exit fullscreen mode
  • Store passwords with hashing (bcrypt / argon2)
import bcrypt from "bcrypt";

const hashed = await bcrypt.hash(password, 10);
Enter fullscreen mode Exit fullscreen mode
  • Never store secrets in code → use env variables
// ❌ BAD
const DB_PASSWORD = "mysecret";

// ✅ GOOD
const DB_PASSWORD = process.env.DB_PASSWORD;
Enter fullscreen mode Exit fullscreen mode
  • Validate ALL inputs (frontend ≠ security)
import Joi from "joi";

const schema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(6).required()
});
Enter fullscreen mode Exit fullscreen mode

👉 At this stage, you block “script kiddies”


2. Authentication Done Right

  • Use JWT / Session-based auth
import jwt from "jsonwebtoken";

const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, {
  expiresIn: "1h"
});
Enter fullscreen mode Exit fullscreen mode
  • Add password rules (length > complexity)
  • Implement rate limiting (login brute force = blocked)
import rateLimit from "express-rate-limit";

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

app.use("/login", limiter);
Enter fullscreen mode Exit fullscreen mode
  • Add email verification

👉 Without this, your app = open gate


3. Authorization (Most Devs Mess This Up)

Authentication = Who are you
Authorization = What can you do

  • Use Role-Based Access Control (RBAC)
function authorize(role) {
  return (req, res, next) => {
    if (req.user.role !== role) {
      return res.status(403).send("Forbidden");
    }
    next();
  };
}

// Usage
app.delete("/admin", authorize("admin"), handler);
Enter fullscreen mode Exit fullscreen mode
  • NEVER trust frontend roles
  • Check permissions on backend EVERY time

Example:

Just because UI hides “Delete” doesn’t mean API should allow it


4. Protect Against Common Attacks

💥 SQL Injection

  • Use prepared statements / ORM
  • Never concatenate queries
// ❌ BAD
db.query(`SELECT * FROM users WHERE email = '${email}'`);

// ✅ GOOD
db.query("SELECT * FROM users WHERE email = ?", [email]);
Enter fullscreen mode Exit fullscreen mode

💥 XSS (Cross-Site Scripting)

  • Escape user input
  • Use Content Security Policy (CSP)
import xss from "xss";

const safeInput = xss(userInput);
Enter fullscreen mode Exit fullscreen mode

💥 CSRF

  • Use CSRF tokens
  • SameSite cookies

👉 These 3 alone stop most real-world attacks

import csrf from "csurf";

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

5. Secure Your APIs

  • Add API rate limiting
  • Use API keys / OAuth
if (req.headers["x-api-key"] !== process.env.API_KEY) {
  return res.status(401).send("Unauthorized");
}
Enter fullscreen mode Exit fullscreen mode
  • Validate request schema (never trust input)
if (!req.body.email) {
  return res.status(400).send("Invalid request");
}
Enter fullscreen mode Exit fullscreen mode

6. Data Protection

  • Encrypt sensitive data at rest
import crypto from "crypto";

const encrypted = crypto.createCipher("aes-256-cbc", key)
  .update(data, "utf8", "hex");
Enter fullscreen mode Exit fullscreen mode
  • Use secure cookies: HttpOnly, Secure, SameSite
res.cookie("token", token, {
  httpOnly: true,
  secure: true,
  sameSite: "strict"
});
Enter fullscreen mode Exit fullscreen mode
  • Don’t expose internal IDs (use UUIDs)

7. Infrastructure Security

  • Use firewall (WAF)
  • Enable logging + monitoring
import morgan from "morgan";

app.use(morgan("combined"));
Enter fullscreen mode Exit fullscreen mode
  • Auto-block suspicious IPs
  • Keep dependencies updated (very important)

8. Advanced Layer (Production-Level)

  • Add 2FA (Two-Factor Authentication)
const otp = Math.floor(100000 + Math.random() * 900000);
Enter fullscreen mode Exit fullscreen mode
  • Implement Zero Trust mindset
  • Use security headers: HSTS, X-Frame-Options, X-Content-Type-Options
import { v4 as uuidv4 } from "uuid";

const userId = uuidv4();
Enter fullscreen mode Exit fullscreen mode

9. Test Like a Hacker

  • Run vulnerability scans
  • Do basic penetration testing
  • Use tools like: Burp Suite, OWASP ZAP

10. Assume Breach (Final Boss Level)

“It’s not if, it’s when.”

  • Log everything important
  • Set up alerts
  • Have a rollback plan
  • Backup regularly
console.error("Unauthorized access attempt", req.ip);
Enter fullscreen mode Exit fullscreen mode

🧩 Final Mental Model

Security = Layers

Input → Auth → Authorization → Validation → Monitoring → Response
Enter fullscreen mode Exit fullscreen mode

Break one layer → others still protect you.


“Perfect security doesn’t exist. But lazy security gets hacked first.”

Top comments (0)