Every API endpoint is a potential attack vector. The difference between a secure API and a vulnerable one is usually not a single catastrophic oversight — it's an accumulation of small gaps. Here's our pre-production API security checklist.
Authentication and authorisation
Use OAuth 2.0 with PKCE for user-facing APIs. Use short-lived JWTs (15-minute expiry) with refresh token rotation. Store refresh tokens in httpOnly, SameSite=Strict cookies — never in localStorage. Validate token signature, expiry, issuer, and audience on every request. Implement proper token revocation.
Rate limiting and throttling
Every endpoint needs rate limiting — not just authentication endpoints. Use a sliding window algorithm rather than fixed windows to prevent burst attacks at window boundaries. Implement per-user, per-IP, and global rate limits. Return Retry-After headers. Use Redis for distributed rate limiting across multiple API instances.
Input validation
Validate all inputs at the API boundary before they touch your business logic. Use a schema validation library (Zod, Joi, class-validator). Reject unexpected fields — don't just ignore them. Enforce maximum lengths on all string fields. Validate content types. Never trust client-supplied IDs without authorisation checks.
HTTPS and transport security
TLS 1.3 only. Disable TLS 1.0 and 1.1. Set HSTS headers with a long max-age. Use certificate pinning in mobile clients. Validate SSL certificates in all server-side HTTP clients — never disable certificate validation.
CORS configuration
Never use Access-Control-Allow-Origin: * on authenticated endpoints. Specify exact origins. Validate the Origin header server-side. Only allow the HTTP methods your API actually uses. Don't expose sensitive headers in Access-Control-Expose-Headers.
Error handling
Return generic error messages to clients. Never expose stack traces, database error messages, or internal implementation details. Log the full error server-side. Use consistent error response schemas — attackers use error message differences to enumerate valid usernames, IDs, and resources.
Security headers
Set X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy, and Referrer-Policy on all responses. Use a library like Helmet.js to manage these systematically.
Audit logging
Log every API call with: timestamp, user ID, IP address, endpoint, HTTP method, response status, and request duration. Never log request bodies containing PII or secrets. Ship logs to a SIEM. Alert on anomalous patterns — high error rates, unusual access times, data export spikes.