API Security Checklist: 15 Things to Audit Before You Go Live
SEP 5, 2024- Written by
Yves SoeteBlacksight LLC visit us to use our free website security scanner onscanner.blacksight.io
Get notified when new articles drop — visitblacksight.io/blog
to subscribe.
APIs are the backbone of modern applications. They connect your frontend to your backend, your mobile app to your database, your microservices to each other, and your platform to third-party integrations. They are also one of the most consistently exploited attack surfaces in production environments. The OWASP API Security Top 10 exists for a reason — APIs fail in predictable, repeatable ways, and most of those failures are preventable with proper review before launch. This is the checklist I run through before any API goes live. It is not theoretical. Every item on this list corresponds to a real vulnerability class I have seen exploited in the wild.
1. Authentication: Get the Foundation Right
Every API endpoint that is not explicitly public must require authentication. Use OAuth 2.0 with short-lived access tokens and refresh token rotation for user-facing APIs. For service-to-service communication, use client credentials flow or mutual TLS. If you are using API keys, treat them as secrets — never embed them in client-side code, never pass them in URL query parameters (they end up in server logs), and implement key rotation policies. Every API key should be scoped to the minimum permissions required.
2. Authorization: Broken Object Level Authorization (BOLA)
BOLA is the number one vulnerability on the OWASP API Security Top 10, and for good reason. It is the most common API vulnerability we find during audits. The pattern is simple: a user requests /api/v1/orders/1234, and the server returns the order without verifying that the authenticated user owns order 1234. The fix requires checking object ownership on every single request. Do not rely on the client to send only valid IDs. Implement authorization middleware that maps the authenticated identity to the requested resource and rejects unauthorized access with a 403, not a 404 — unless you want to prevent enumeration, in which case 404 is acceptable.
3. Rate Limiting and Throttling
Every API needs rate limiting. Without it, you are vulnerable to brute force attacks, credential stuffing, data scraping, and denial-of-service. Implement rate limits per API key, per user, and per IP address. Use sliding window algorithms rather than fixed windows to prevent burst abuse at window boundaries. Return 429 Too Many Requests with a Retry-After header. For authentication endpoints specifically, apply much stricter limits — no more than 5-10 attempts per minute. Consider implementing exponential backoff requirements for repeated failures.
4. Input Validation and SQL Injection Prevention
Validate every input on the server side. Client-side validation is for user experience, not security. Define strict schemas for request bodies, query parameters, and path parameters. Reject anything that does not conform. Use parameterized queries or an ORM for all database interactions — never concatenate user input into SQL strings. Validate data types, string lengths, numeric ranges, and allowed character sets. For file uploads, validate MIME types on the server (not just the file extension), enforce size limits, and never store uploaded files in a publicly accessible directory with execute permissions.
5. CORS Configuration
Cross-Origin Resource Sharing misconfiguration is one of the easiest mistakes to make and one of the most dangerous. Never set Access-Control-Allow-Origin to * on APIs that handle authenticated requests. Whitelist specific origins explicitly. Do not reflect the Origin header back as the allowed origin without validation — attackers set arbitrary origins. Be careful with Access-Control-Allow-Credentials: true, as it allows cookies to be sent cross-origin. If you need it, the allowed origin must be a specific domain, never a wildcard. Audit your CORS headers with every deployment.
6. HTTPS Enforcement and Transport Security
All API traffic must use TLS. There are no exceptions. Redirect HTTP to HTTPS at the load balancer level. Set the Strict-Transport-Security header with a long max-age (at least one year) and include subdomains. Use TLS 1.2 as the minimum version and prefer TLS 1.3. Disable weak cipher suites. For high-security APIs, implement certificate pinning in mobile clients and consider mutual TLS for service-to-service calls where both sides present certificates.
7. Error Handling: Stop Leaking Information
Production APIs must never return stack traces, database error messages, or internal file paths. These details give attackers a roadmap of your architecture. Return generic error messages to the client and log the full details server-side. Standardize your error response format. Use appropriate HTTP status codes but do not over-specify — a 500 Internal Server Error is sufficient for the client; the details belong in your logs. Be careful with validation errors too. Telling a user "email not found" on a login endpoint confirms that the email does not exist in your system, enabling enumeration. Use consistent messages like "invalid credentials" regardless of whether the email or password was wrong.
// Bad - leaks internal details
{"status": 500, "error": "NullPointerException at UserService.java:142"}
// Good - generic client response
{"status": 500, "error": "An internal error occurred. Please try again later."}
8. Logging, Monitoring, and Alerting
Log every API request with enough detail to reconstruct what happened during an incident: timestamp, authenticated identity, endpoint, HTTP method, response status, response time, and client IP. Do not log sensitive data — request bodies containing passwords, tokens, or PII should be redacted or excluded. Set up alerts for anomalous patterns: sudden spikes in 401/403 responses, unusual request volumes from a single source, requests to non-existent endpoints, and latency spikes that could indicate injection attacks hitting the database. If you cannot detect an attack in progress, you cannot respond to it.
9. API Versioning and Deprecation Strategy
Version your API from day one. Use URL path versioning (/v1/, /v2/) for simplicity or header-based versioning for cleaner URLs. When you release a new version, set a clear deprecation timeline for the old one — typically 6-12 months. Communicate deprecation through response headers (Deprecation and Sunset headers), documentation, and direct notification to consumers. The security concern here is that old API versions often lack security patches applied to newer versions. Running deprecated versions indefinitely means maintaining multiple security surfaces. Shut them down on schedule.
10. Payload Size Limits and Mass Assignment
Set maximum payload sizes at both the web server and application level. An unbounded POST body is an invitation for denial-of-service. For JSON APIs, a 1MB limit is generous for most use cases. Mass assignment is a subtler problem. If your API accepts a JSON body and blindly maps it to a database model, an attacker can send fields they should not control — like role: "admin" or is_verified: true. Whitelist the exact fields you accept for each endpoint. In frameworks that support it, use separate input schemas for creation and update operations.
// Attacker sends unexpected fields
POST /api/v1/users
{"name": "attacker", "email": "[email protected]", "role": "admin"}
// Your API should only accept whitelisted fields
allowed_fields = ["name", "email"]
11. JWT Best Practices
If you use JSON Web Tokens, get the implementation right. Use asymmetric algorithms (RS256 or ES256) so that the signing key and verification key are separate. Never use the "none" algorithm — your JWT library should reject it by default, but verify this. Set short expiration times for access tokens (15 minutes is a reasonable default) and use refresh tokens for session continuity. Store JWTs in HttpOnly, Secure cookies rather than localStorage to prevent XSS-based token theft. Validate the issuer, audience, and expiration claims on every request. Do not store sensitive data in the JWT payload — it is base64-encoded, not encrypted.
12. API Gateway and Defense in Depth
An API gateway provides a centralized enforcement point for authentication, rate limiting, request validation, and logging. It decouples these cross-cutting concerns from your application code. Use it to terminate TLS, validate API keys, enforce rate limits, and route requests to backend services. The gateway should also handle request transformation, response caching, and circuit breaking. Popular options include Kong, AWS API Gateway, and Envoy. Even with a gateway, implement security checks in your application layer — defense in depth means no single layer is the sole protector.
13. Final Pre-Launch Checks
Before going live, run through these final items. Verify that debug mode is disabled and development endpoints are removed. Confirm that sensitive headers (X-Powered-By, Server version) are stripped or generalized. Test every endpoint with expired tokens, invalid tokens, missing tokens, and tokens belonging to different users. Send malformed JSON, oversized payloads, and unexpected content types. Verify that 404 responses for missing resources are indistinguishable from 403 responses for unauthorized resources (to prevent enumeration). Check that all database queries use parameterized statements. Confirm that file upload endpoints validate content on the server. Run an automated security scan — tools like Blacksight's API scanner can identify common misconfigurations before an attacker does.
Bonus: Use our free website vulnerability scanner at
scanner.blacksight.io
Liked this article? Get notified when new articles drop! visitblacksight.io/blog
to subscribe