API Security

API Security Best Practices for Modern Applications

Essential API security practices including authentication, rate limiting, input validation, and protecting against common API vulnerabilities.

Hacker Bot Team

Security Team

API security shield protecting data flow

APIs are the backbone of modern applications. They’re also the most common attack vector. Here’s how to build APIs that don’t break under pressure.

The API Security Problem

Your API is public by nature. Unlike traditional web apps where you control the interface, APIs expose raw functionality that anyone can probe. Every endpoint is a potential entry point.

Authentication Done Right

Use OAuth 2.0 / OpenID Connect

JWT tokens are standard, but implementation matters:

// Verify JWT with proper options
const verified = jwt.verify(token, publicKey, {
  algorithms: ['RS256'], // Specify allowed algorithms
  issuer: 'https://auth.yoursite.com',
  audience: 'your-api',
  clockTolerance: 30, // Allow 30 seconds of clock skew
});

Short-Lived Tokens

  • Access tokens: 15 minutes max
  • Refresh tokens: 7 days with rotation
  • API keys: Rotate quarterly at minimum

Rate Limiting

Without rate limiting, your API is vulnerable to:

  • Brute force attacks
  • Denial of service
  • Credential stuffing
// Example rate limiting middleware
const rateLimit = require('express-rate-limit');

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

app.use('/api/', apiLimiter);

Input Validation

Never trust client data. Validate everything:

import { z } from 'zod';

const CreateUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
  role: z.enum(['user', 'admin']),
});

function createUser(data: unknown) {
  const validated = CreateUserSchema.parse(data);
  // Now safe to use
}

Authorization Patterns

Authentication answers “who are you?” Authorization answers “what can you do?”

Resource-Based Authorization

async function getDocument(userId, documentId) {
  const doc = await db.documents.find(documentId);
  
  // Check ownership or explicit sharing
  if (doc.ownerId !== userId && !doc.sharedWith.includes(userId)) {
    throw new ForbiddenError();
  }
  
  return doc;
}

Role-Based Access Control (RBAC)

const permissions = {
  admin: ['read', 'write', 'delete', 'manage'],
  editor: ['read', 'write'],
  viewer: ['read'],
};

function canAccess(userRole, requiredPermission) {
  return permissions[userRole]?.includes(requiredPermission) ?? false;
}

CORS Configuration

Misconfigured CORS is a common vulnerability:

// DANGEROUS - allows any origin
app.use(cors({ origin: '*' }));

// SECURE - whitelist allowed origins
app.use(cors({
  origin: ['https://app.yoursite.com', 'https://admin.yoursite.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
}));

Error Handling

Don’t leak information through errors:

// BAD - leaks implementation details
catch (error) {
  res.status(500).json({ error: error.message, stack: error.stack });
}

// GOOD - generic error for clients, detailed logging server-side
catch (error) {
  logger.error('Database error', { error, requestId });
  res.status(500).json({ error: 'Internal server error', requestId });
}

Conclusion

API security isn’t a feature—it’s a requirement. Start with authentication, add authorization, validate everything, and monitor relentlessly. Your users are counting on it.


Hacker Bot’s API security testing finds vulnerabilities in your endpoints before attackers do. Try it on your API today.