Authentication answers the question "who are you?" It does not answer "should you be doing that?", "how fast should you be allowed to do it?", or "is what you are sending safe to process?" Most API breaches in the last five years exploited vulnerabilities that had nothing to do with stolen credentials. They exploited missing rate limits, broken authorization, poor input validation, and exposed data.
If your API security strategy stops at authentication, you are leaving the front door locked while the windows are wide open. Here is what comes after.
The OWASP API Security Top 10
The OWASP API Security Top 10 (2023 edition) provides a useful framework for understanding where APIs fail. The top risks are:
1. Broken Object Level Authorization (BOLA). A user can access another user's data by changing an ID in the request. This is the most common API vulnerability.
2. Broken Authentication. Weak authentication mechanisms.
3. Broken Object Property Level Authorization. A user can read or modify object properties they should not have access to.
4. Unrestricted Resource Consumption. No rate limiting, allowing denial of service or cost inflation.
5. Broken Function Level Authorization. A regular user can access admin endpoints.
6. Unrestricted Access to Sensitive Business Flows. Automated abuse of legitimate business processes (scalping, credential stuffing, scraping).
7. Server Side Request Forgery (SSRF). The API can be tricked into making requests to internal systems.
8. Security Misconfiguration. Default configurations, unnecessary features enabled, missing security headers.
9. Improper Inventory Management. Old API versions still running, undocumented endpoints exposed.
10. Unsafe Consumption of APIs. Trusting data from third party APIs without validation.
Notice that only one of these ten risks is about authentication. The other nine are about what happens after the user is authenticated. Let us address the most critical ones.
Rate Limiting: More Than DDoS Protection
Rate limiting is not just about preventing denial of service attacks. It is about controlling the cost, performance, and abuse surface of your API. A well designed rate limiting strategy addresses multiple concerns.
Per user rate limits prevent any single user (or compromised account) from consuming disproportionate resources. A typical starting point is 100 requests per minute for standard endpoints and 10 per minute for expensive operations (search, report generation, file uploads).
Per endpoint rate limits protect expensive operations independently. Your health check endpoint can handle 1,000 requests per minute without concern. Your database intensive search endpoint might need a limit of 20 requests per minute per user.
Global rate limits protect your infrastructure from traffic spikes regardless of source. This is your safety net when per user limits are not enough.
Implementation matters. Use a sliding window algorithm rather than fixed windows to prevent burst abuse at window boundaries. Store rate limit state in a fast, distributed store like Redis. Return proper HTTP 429 responses with `Retry-After` headers so clients know when they can try again. Include rate limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`) in every response so clients can self regulate.
```
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1708700000
```
Tiered rate limits based on subscription level let you monetize API access while protecting your infrastructure. Free tier gets 60 requests per minute. Paid tier gets 600. Enterprise gets custom limits. This is a business model and a security control in one.
We covered rate limiting as part of our broader API design best practices guide. It is worth reading alongside this post.
Input Validation: Trust Nothing
Every piece of data that enters your API is a potential attack vector. Input validation is not about displaying friendly error messages. It is about preventing injection attacks, data corruption, and business logic abuse.
Validate at the boundary. Every API endpoint should validate every input field before any processing begins. Do not rely on your database constraints or downstream services to catch invalid data. By the time bad data reaches your database, it may have already caused damage.
Type validation. If a field should be a number, reject strings. If it should be a UUID, validate the format. If it should be an email, validate the structure. Use schema validation libraries (Zod, Joi, JSON Schema) to define and enforce input shapes.
Range validation. A quantity field should not accept negative numbers or numbers above a reasonable maximum. A date field should not accept dates 100 years in the future. A text field should have a maximum length. Every numeric and string field needs bounds.
Business logic validation. A user should not be able to transfer more money than their balance. A start date should not be after an end date. A discount should not exceed 100 percent (or whatever your maximum is). These validations prevent business logic abuse that technical validation alone cannot catch.
SQL injection and NoSQL injection. Use parameterized queries. Always. There is no excuse for string concatenation in database queries in 2026. ORMs and query builders handle this automatically, but verify that any raw queries use parameterization.
Cross site scripting (XSS). If your API returns user generated content, sanitize output. Even if your frontend handles sanitization, your API should not return raw unsanitized HTML. Defense in depth means sanitizing at both layers.
File upload validation. If your API accepts file uploads, validate file type (by content, not just extension), enforce size limits, scan for malware, and store uploaded files in an isolated storage location, never in your application directory.
Authorization: The Forgotten Layer
Authentication tells you who the user is. Authorization tells you what they are allowed to do. The gap between these two is where most API breaches occur.
Object level authorization. Every API request that accesses a specific resource must verify that the authenticated user has permission to access that specific resource. This means checking ownership or permission on every single request, not just checking that the user has a valid token.
```
// Wrong: only checks authentication
GET /api/invoices/123
// If user A requests user B's invoice, it returns it
// Right: checks authorization
GET /api/invoices/123
// Server verifies invoice 123 belongs to the authenticated user
```
This is BOLA (Broken Object Level Authorization), the number one API vulnerability. It is trivially easy to exploit: an attacker just changes the ID in the URL. It is also trivially easy to prevent: check ownership on every request.
Function level authorization. Admin endpoints must verify admin role, not just valid authentication. A common pattern is to have admin routes that are protected by authentication middleware but lack role verification. An authenticated regular user discovers the admin endpoint and has full access.
Field level authorization. A user updating their profile should be able to change their name but not their role, subscription tier, or account balance. Validate that the request only modifies fields the user is authorized to modify. Reject or ignore unauthorized field changes.
Encryption Beyond TLS
TLS protects data in transit. It does not protect data at rest, data in logs, data in error messages, or data exposed through API responses.
Response filtering. Never return more data than the client needs. If your database user object has 30 fields including password hashes, internal flags, and admin notes, your API response should only include the fields the client is authorized to see. Use explicit allowlists (not blocklists) for response fields.
Sensitive data in URLs. Query parameters appear in server logs, browser history, and proxy logs. Never put sensitive data (tokens, passwords, personal information) in URLs. Use request bodies or headers instead.
Error message leakage. A detailed error message that says "User with email john@example.com not found" confirms that email does not exist in your system. An error that says "Invalid credentials" reveals nothing. Internal errors should return generic messages to clients while logging details server side.
Logging hygiene. Your API logs should never contain passwords, tokens, credit card numbers, or personal health information. Implement automatic redaction for sensitive fields in your logging middleware. This is especially critical for applications subject to compliance requirements like PCI or HIPAA.
API Versioning and Deprecation
Old API versions are a security liability. They often lack security controls added to newer versions, run on outdated dependencies, and receive less testing and monitoring.
Maintain an API inventory. Document every endpoint, its version, and its status (active, deprecated, sunset). Unknown or forgotten endpoints are a common attack vector.
Deprecate aggressively. When a new API version is released, set a clear sunset date for the old version. Communicate the timeline to clients. Monitor usage of deprecated versions and follow up with active users.
Remove sunset APIs. A deprecated API that still runs is still an attack surface. When the sunset date arrives, turn it off. Do not leave it running "just in case."
Security Headers and CORS
CORS (Cross Origin Resource Sharing). Configure it explicitly. Never use wildcard origins (`*`) for APIs that handle authenticated requests. Whitelist specific origins that are authorized to call your API.
Security headers. Every API response should include:
- `Strict-Transport-Security` to enforce HTTPS
- `X-Content-Type-Options: nosniff` to prevent MIME type sniffing
- `X-Frame-Options: DENY` to prevent framing
- `Content-Security-Policy` appropriate to your response types
Request size limits. Set maximum request body sizes at your web server and application level. A 10GB POST request should be rejected before it consumes server resources.
Monitoring and Incident Detection
Security without monitoring is security theater. You need to detect attacks in progress, not just discover them in a post mortem.
Anomaly detection. Flag unusual patterns: a user accessing 10,000 records in a minute, authentication failures from a single IP, requests to endpoints that do not exist, and geographic anomalies in access patterns.
Real time alerting. When anomalies are detected, alert your team immediately. Not in a daily report. Immediately. The difference between a contained incident and a breach is often minutes.
API access logging. Log every API request with enough detail to reconstruct what happened during an incident: timestamp, authenticated user, endpoint, request parameters (redacted), response code, and response time. Retain these logs for at least one year.
Building secure APIs requires deliberate architectural decisions at every layer, from network infrastructure to application logic to monitoring. Our team handles full stack development with security built into every layer, not bolted on after the fact. If your API security needs an audit or your next project needs to be built securely from the start, let us talk.