Best PracticesNov 22, 20255 min read

API Security: Protecting Your Backend in Production

Essential security practices every developer should know

JWTOAuthExpress
API Security: Protecting Your Backend in Production

Key Takeaways

  • JWT implementation patterns
  • Rate limiting strategies
  • Common vulnerability prevention

Security isn't optional – it's foundational. Every API endpoint is a potential attack vector. Here's how to build secure APIs from the ground up.

Authentication Done Right

JWT is popular, but implementation details matter enormously:

javascript
// Secure JWT implementation
const jwt = require('jsonwebtoken');

function generateTokens(user) {
  const accessToken = jwt.sign(
    { id: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }  // Short-lived
  );
  
  const refreshToken = jwt.sign(
    { id: user.id },
    process.env.REFRESH_SECRET,
    { expiresIn: '7d' }
  );
  
  return { accessToken, refreshToken };
}

Rate Limiting

Protect against brute force and DDoS attacks with intelligent rate limiting:

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

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // Limit each IP to 100 requests per window
  message: { error: 'Too many requests, try again later' },
  standardHeaders: true,
  legacyHeaders: false,
});

// Stricter limits for auth endpoints
const authLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 5, // 5 failed attempts
  skipSuccessfulRequests: true,
});

Input Validation

Never trust client input. Validate everything:

javascript
const { body, validationResult } = require('express-validator');

const createUserValidation = [
  body('email').isEmail().normalizeEmail(),
  body('password')
    .isLength({ min: 8 })
    .matches(/^(?=.*[A-Z])(?=.*[0-9])/),
  body('name').trim().escape().isLength({ min: 2, max: 50 }),
];

function validate(req, res, next) {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  next();
}

Security Headers

Set security headers to prevent common attacks:

javascript
const helmet = require('helmet');

app.use(helmet());
app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    styleSrc: ["'self'", "'unsafe-inline'"],
    scriptSrc: ["'self'"],
    imgSrc: ["'self'", "data:", "https:"],
  }
}));

Security Checklist

  • Always use HTTPS in production
  • Store secrets in environment variables
  • Implement proper CORS configuration
  • Log security events for monitoring
  • Keep dependencies updated
  • Use parameterized queries for database operations
HR

Written by Hammas Rashid

Full-Stack Developer passionate about building scalable web applications and sharing knowledge with the developer community.

Chat on WhatsApp