API Security Fundamentals: What Every Developer Needs to Know
API security failures are not exotic. They rarely involve sophisticated attacks on cryptographic primitives or novel zero-day exploits. The most consequential breaches — the ones that expose millions of records, compromise user accounts, or shut down services — happen because an API allowed something it should not have, at a scale its designers did not anticipate. Understanding the fundamental attack surface of an API and designing against it deliberately is the entire discipline. It is not advanced knowledge. It is the baseline.
HTTPS Everywhere, Without Exception
No API exposed to the internet should operate over HTTP. Full stop. HTTP transmits all data in plaintext, which means any network intermediary — a misconfigured router, a coffee shop access point, a CDN misconfiguration — can read or modify requests and responses. Authentication tokens, API keys, user data, and any request body are visible and mutable in transit.
TLS (the protocol underlying HTTPS) encrypts the connection and provides authentication that you are talking to the server you intend to talk to, not an interceptor. It is not optional. It does not add meaningful latency for modern applications. Every hosting environment, cloud provider, and API gateway supports it automatically or with minimal configuration.
Beyond requiring HTTPS, configure it correctly: use TLS 1.2 or 1.3, disable older TLS versions and weak cipher suites, and consider HTTP Strict Transport Security (HSTS) headers to tell browsers and clients to always use HTTPS regardless of how a URL is specified.
Authentication vs Authorization: Both Must Be Correct
Authentication answers “who is this?” Authorization answers “what are they allowed to do?” These are distinct problems that require separate implementation, and failures in either create different categories of vulnerability.
Authentication failures: accepting expired tokens, not verifying token signatures, accepting tokens from unexpected issuers, insufficient validation of API keys (accepting any key that looks like the right format). Fix by using well-audited authentication libraries rather than implementing token validation by hand, and by testing invalid token scenarios explicitly.
Authorization failures are more common and more varied. The OWASP API Security Top 10 identifies broken object-level authorization as the leading vulnerability in APIs. This is the pattern: an API returns a resource at /orders/1234, and a client who is authenticated as User A can access /orders/5678, which belongs to User B, simply by changing the ID. The API verifies that the client is authenticated; it does not verify that the authenticated client owns the requested resource.
Every object-level access must verify ownership or permission, not just authentication. For every endpoint that takes a resource identifier, check that the authenticated caller has the right to access that specific resource. This check cannot be assumed or approximated — it must be explicit in every handler.
Function-level authorization is the same problem applied to actions: a non-admin user calling an admin endpoint. Admin routes must verify admin-level permissions, not merely authentication. Obscurity is not access control; if the admin endpoint path is guessable, it will be guessed.
Input Validation: Trust Nothing Incoming
Every piece of data arriving at an API is untrusted until validated. This is not paranoia — it is the correct model for any system with multiple callers.
Validate type, format, range, and length for every input field. Reject requests that fail validation immediately with a clear error, rather than passing malformed input deeper into the system where it might cause unexpected behavior. Use an allowlist approach (explicitly define what is acceptable) rather than a denylist (trying to reject known bad values), because denylist approaches always miss cases.
SQL injection via API parameters is now rarely exploitable in applications using modern ORMs with parameterized queries, but it remains possible in legacy systems and in any code path that constructs queries via string interpolation. Use parameterized queries everywhere.
Mass assignment vulnerabilities occur when an API binds incoming JSON directly to a data model without filtering, allowing a client to set fields the API never intended to expose — including role fields, admin flags, or other privileged attributes. Explicitly define which fields an endpoint accepts and reject anything outside that list.
Sensitive Data Exposure
Only return data that is actually needed. An API endpoint returning a user profile has no reason to include the user’s hashed password, their full payment card number, or internal flags used only by your backend systems. Strip sensitive fields from responses explicitly, and audit response schemas periodically for data that should not be there.
For data in transit, HTTPS handles encryption. For particularly sensitive fields — financial data, government IDs, health information — consider additional application-level controls around what can be requested and by whom.
Log carefully. Access logs should record what was requested and by whom. But application logs should not contain request bodies in raw form if those bodies include authentication tokens, passwords, or sensitive personal data. Logs are often less protected than your primary data stores, and log data that contains credentials or personal information creates a secondary exposure risk.
Rate Limiting as a Security Control
Rate limiting is often framed as a reliability feature. It is also a security control. Credential stuffing attacks — using large lists of known username/password combinations to attempt logins — depend on the ability to make thousands of requests quickly. Brute force attacks on PINs, OTPs, or short tokens require high request volume. Without rate limiting on authentication endpoints and sensitive operations, these attacks are computationally cheap.
Apply stricter rate limits to authentication endpoints, password reset flows, and any endpoint that allows enumeration of sensitive data. Consider rate limiting per IP address in addition to per account for unauthenticated or pre-authentication endpoints.
Dependency Security
An API’s security surface extends to every library and dependency it uses. Vulnerabilities in authentication libraries, HTTP parsing code, and serialization libraries have produced critical exploits across the industry. Keep dependencies updated, monitor security advisories for packages you depend on, and treat a dependency with a known critical vulnerability as a blocking issue, not a backlog item.
Security Is Not a Phase
The pattern of “build first, secure later” produces APIs that carry fundamental vulnerabilities from their first deployment. Security controls that must be added after the fact are harder to implement correctly because they work against an architecture that was not designed to accommodate them.
The controls above are not exotic: HTTPS, correct authentication, object-level authorization checks, input validation, sensitive data minimization, rate limiting. They are table stakes. An API that implements all of them correctly has addressed the majority of the attack surface that actually produces breaches. The sophistication comes later. The fundamentals come first, and they come during design, not after deployment.