- APIs are the most frequently attacked component of modern applications. The OWASP API Security Top 10 describe the most critical risks.
- Authentication (who are you?) and authorization (what are you allowed to do?) are two different things. Both must be verified server-side with every API request.
- OAuth 2.0 with PKCE is the current standard for API authentication. API keys alone are not sufficient for user-based APIs.
- Rate limiting protects against brute force, credential stuffing, and denial of service. Implement it at multiple levels: per IP, per user, and per endpoint.
- Input validation is the last line of defense against injection attacks. Validate the type, format, length, and value range of every input server-side.
Why API Security Is Its Own Topic
APIs (Application Programming Interfaces) are the interfaces through which applications communicate with each other. Your frontend talks to the backend via a REST API. Your backend talks to external services via APIs (payment providers, email providers, cloud storage). Your mobile app uses the same API as your web frontend.
This means: APIs expose business logic, data, and functionality. Every API endpoint is a potential attack vector. And unlike a web interface operated by a human, APIs are called by software, enabling automated attacks at massive scale.
The attack patterns against APIs differ in some respects from those against traditional web applications. That is why OWASP, in addition to the general Top 10, has published a separate API Security Top 10 that specifically addresses API-specific risks.
OWASP API Security Top 10: The Most Critical Risks
The OWASP API Security Top 10 (2023 version) identify the following risks:
-
Broken Object Level Authorization (BOLA): The API does not check whether the user is authorized to access the requested object. By changing an ID in the URL, a user can access other users' data.
-
Broken Authentication: Weak or missing authentication mechanisms. API keys that can be easily guessed, missing token rotation, no protection against token theft.
-
Broken Object Property Level Authorization: The API returns more properties of an object than necessary (Excessive Data Exposure) or accepts input for properties that the user should not be allowed to change (Mass Assignment).
-
Unrestricted Resource Consumption: No rate limiting, no limit on request sizes, no limit on batch operations. An attacker can flood the API with requests or query enormous amounts of data.
-
Broken Function Level Authorization: Users can access API endpoints intended for higher permission levels (e.g., admin functions).
-
Unrestricted Access to Sensitive Business Flows: Automated abuse of business functions (e.g., mass account creation, automated purchase of inventory).
-
Server-Side Request Forgery (SSRF): The API fetches a user-controlled URL, enabling access to internal systems.
-
Security Misconfiguration: Missing CORS configuration, detailed error messages, unnecessary HTTP methods.
-
Improper Inventory Management: Outdated API versions that are still reachable, undocumented endpoints, missing API inventory.
-
Unsafe Consumption of APIs: Blind trust in data from third-party APIs without validating it.
Authentication: Who Are You?
Authentication proves the identity of the caller. The most common mechanisms for APIs are API keys, OAuth 2.0, and JWTs.
API Keys
API keys are simple, randomly generated strings sent with every request (typically in the X-API-Key header or as a query parameter). They identify the calling application, not the individual user.
When API keys make sense: Server-to-server communication where one application acts on behalf of another application (not on behalf of a user). Public APIs with usage limits (the key identifies the developer, not the end user).
When API keys are not enough: When you need to know which user is performing the action (e.g., "User A reads their own data, not User B's data"). API keys cannot represent this because they do not carry user identity.
Security measures for API keys: Generate keys with sufficient entropy (at least 32 bytes, random). Transmit keys only over HTTPS. Store keys hashed in the database, not in plaintext. Implement key rotation: users should be able to regularly renew their keys. Issue different keys for different permission levels (read key, write key).
OAuth 2.0
OAuth 2.0 is the de facto standard for API authentication in scenarios where a user grants an application access to their data at another service. But even for your own APIs, OAuth 2.0 is the recommended approach because it enables a clean separation of authentication and authorization.
The most important OAuth 2.0 flows are the Authorization Code Flow with PKCE (for web and mobile apps where a user logs in), the Client Credentials Flow (for server-to-server communication where no user is involved), and the Device Authorization Flow (for devices without a browser, e.g., smart TVs, CLI tools).
The Implicit Flow and the Resource Owner Password Credentials Flow are considered deprecated and should no longer be used.
Practical tip: Use an established identity provider (Keycloak, Auth0, Azure AD, AWS Cognito) instead of implementing OAuth 2.0 yourself. Integration via SSO significantly simplifies identity management. The correct implementation is complex, and errors lead to severe security vulnerabilities.
JSON Web Tokens (JWT)
JWTs are self-describing tokens that contain information about the user (claims) and are cryptographically signed. They are frequently used as access tokens in OAuth 2.0 implementations.
Security measures for JWTs: Use asymmetric signing (RS256 or ES256) instead of symmetric (HS256), because with HS256 anyone who knows the key can also create tokens. Set short validity periods (5-15 minutes for access tokens). Validate the signature, issuer (iss), audience (aud), and expiration (exp) with every request. Never use alg: none and never accept it (a known JWT attack). Do not store sensitive data in the JWT payload, as JWTs are only signed, not encrypted. The payload is Base64-encoded and readable by anyone.
Authorization: What Are You Allowed to Do?
Authentication and authorization are two different concepts but are often confused or conflated. Authentication establishes who you are. Authorization establishes what you may do. Both must be checked with every API request.
Object-Level Authorization
With every access to a resource, check whether the authenticated user is allowed to access that specific resource. Not just "may User A read orders," but "may User A read the order with ID 42."
This is the countermeasure against BOLA (Broken Object Level Authorization), the most common API security risk. In practice, the implementation looks like this: your database query always filters by the currently authenticated user. Instead of SELECT * FROM orders WHERE id = ?, you write SELECT * FROM orders WHERE id = ? AND user_id = ?. This makes it technically impossible to access other people's data, regardless of what the user changes in the URL.
Function-Level Authorization
With every endpoint, check whether the user has the required role or permission. Admin endpoints must verify that the user is an administrator. Management endpoints must verify that the user is a manager.
Implement authorization as middleware or a decorator, not individually in each controller. A centralized authorization mechanism is easier to maintain and harder to forget.
Principle of Least Privilege
Give API clients only the minimum necessary permissions. OAuth 2.0 scopes are excellent for this: a client that only needs to read data gets the scope read:orders. A client that also needs to write gets write:orders in addition. A client that needs to manage users gets admin:users.
Rate Limiting: Preventing Abuse
Rate limiting restricts the number of requests a client can send within a defined time period. It protects against various types of attacks.
Why Rate Limiting Is Essential
Brute-force attacks: Without rate limiting, an attacker can perform thousands of login attempts per second and guess passwords through trial and error.
Credential stuffing: The attacker automatically tests stolen credentials (from data breaches) against your API. Multi-factor authentication provides additional protection. With millions of credentials in the list, rate limiting is the only defense.
Denial of service: Without rate limiting, a single client can flood the API with so many requests that it becomes unusable for all other users.
Data exfiltration: A compromised API key is used to read the entire database via the API. Rate limiting restricts the amount of data that can be queried per time unit.
Implementation Strategies
Fixed window: Maximum N requests per minute. Simple to implement, but has a drawback: at the boundary of two time windows, briefly 2N requests can come through (N at the end of one window, N at the beginning of the next).
Sliding window: Fixes the boundary case of the fixed window by considering a sliding time period. More complex to implement, but more accurate.
Token bucket: Each client has a "bucket" with tokens. Each request consumes a token. The bucket is refilled at a fixed rate. When the bucket is empty, requests are rejected. Allows short bursts (the bucket can be full) but limits the average.
Leaky bucket: Similar to token bucket, but requests are processed evenly, not in bursts. For APIs that prefer even load.
Multi-Level Rate Limiting
Implement rate limiting at multiple levels.
Global: Maximum 10,000 requests per minute for the entire API (protects against DDoS).
Per IP: Maximum 100 requests per minute per IP address (protects against individual attackers).
Per user: Maximum 60 requests per minute per authenticated user (protects against compromised accounts).
Per endpoint: Sensitive endpoints (login, password reset) have stricter limits than read endpoints. E.g., login: maximum 5 attempts per minute, data reading: maximum 100 requests per minute.
HTTP Headers for Rate Limiting
Inform the client about the applicable limits with standardized HTTP headers: X-RateLimit-Limit (maximum requests in the time window), X-RateLimit-Remaining (remaining requests), X-RateLimit-Reset (time when the window resets), and Retry-After (wait time in seconds when the limit is reached).
When the limit is reached, respond with HTTP 429 (Too Many Requests).
Input Validation: Trust No Input
Input validation is the most fundamental and simultaneously the most frequently missing security measure. Every input your API receives — whether from the body, query parameters, headers, or path — is potentially malicious and must be validated.
Validation Levels
Type validation: Is the input of the expected type? If you expect a number, ensure the input is actually a number and not a string containing SQL code.
Format validation: Does the input match the expected format? Email addresses, phone numbers, dates, UUIDs have defined formats.
Value range validation: Is the input within the valid range? An age should be between 0 and 150, not -1 or 999999.
Length validation: Is the input not too long? A name with 10,000 characters is probably not a name but an attack.
Business logic validation: Is the input valid in the business context? An order quantity of -5 should be rejected, even though -5 is a valid number.
Schema Validation
For REST APIs with JSON payloads, JSON Schema is a powerful tool for input validation. You define a schema that describes the expected structure, types, formats, and value ranges, and validate every incoming request against this schema.
If you have an OpenAPI specification (Swagger) for your API, you can use the schemas defined therein directly for validation. Tools like express-openapi-validator (Node.js), connexion (Python), or OpenAPI middleware for other frameworks handle validation automatically.
Sanitization vs. Validation
Validation checks whether the input is valid and rejects it if invalid. Sanitization modifies the input to make it "safe" (e.g., removing HTML tags). Prefer validation over sanitization. If an input is invalid, reject it rather than trying to repair it. Sanitization can lead to unexpected behavior and is more error-prone.
API Security in Practice: Checklist
Here is a compact checklist you can go through for every API.
Authentication: Every endpoint requires authentication (except explicitly public endpoints). OAuth 2.0 or API keys (depending on the use case). Token validity period appropriately short.
Authorization: Object-level authorization with every data access. Function-level authorization with every endpoint. Least privilege for API clients and scopes.
Rate limiting: Global limit, per-IP limit, per-user limit. Stricter limits for sensitive endpoints. HTTP 429 responses with Retry-After header.
Input validation: All inputs validated (type, format, length, value range). Schema validation for JSON payloads. No assumption that the frontend has validated.
Transport encryption: HTTPS everywhere. TLS 1.2 or higher. HSTS header. Your encryption strategy should define the standards as binding.
Error handling: No stack traces or internal details in error messages. Standardized error responses (e.g., RFC 7807 Problem Details). Log errors, but give the client only general information.
Logging and monitoring: Log all authentication-related events. Detect anomalies (unusually many requests, access to other users' data). Alerting on suspicious patterns.
Documentation: All endpoints documented (OpenAPI/Swagger). Authentication requirements documented. Deprecated endpoints deprecated and shut down after a transition period.
API Security and Regulatory Requirements
APIs are not an isolated technical topic. They fall under the general requirements for secure development and operation.
NIS2 requires secure development practices (Article 21, Paragraph 2e), and APIs are an essential part of every modern application. ISO 27001 Annex A, Control A.8.26 (Application security requirements), requires that security requirements for applications are identified and implemented. An API security policy that addresses authentication, authorization, rate limiting, and input validation is the evidence that you meet this requirement for your APIs. In ISMS Lite, the API security policy with authentication standards and checkpoints can be centrally documented and linked to ISO 27001 controls.
API Versioning and Lifecycle
APIs evolve. New endpoints are added, existing ones change, old ones become obsolete. Without a clear versioning strategy, you risk that outdated and potentially insecure API versions continue to operate because clients still access them.
The most common versioning strategies are URL-based versioning (/api/v1/users, /api/v2/users), header-based versioning (Accept: application/vnd.myapi.v2+json), and query parameter versioning (/api/users?version=2). URL-based versioning is the most widespread and simplest variant.
For security, it is critical that you decommission old API versions after a defined transition period. An API version that has not been maintained for two years may contain vulnerabilities that have long been fixed in newer versions. Document the lifecycle of each API version: introduction date, deprecation date, end-of-life date.
API Gateway as a Central Security Layer
An API gateway is a reverse proxy that sits in front of your API servers and provides centralized security functions: authentication, rate limiting, IP whitelisting, request validation, logging, and TLS termination.
Common API gateways are Kong (open source, plugin architecture), Traefik (open source, good for containers/Kubernetes), AWS API Gateway (managed service), Azure API Management (managed service), and NGINX (as a reverse proxy with Lua extensions).
The advantage of an API gateway: you implement security functions once centrally instead of in each API individually. When you need to change rate limiting or authentication, you change it at the gateway, not in 20 different microservices.
Further Reading
- OWASP Top 10 für Entwickler: Die häufigsten Schwachstellen vermeiden
- Secure Development Lifecycle (SDL): Sicherheit in den Entwicklungsprozess einbauen
- Secrets Management: Passwörter, API-Keys und Zertifikate sicher verwalten
- Container-Sicherheit: Docker und Kubernetes im Mittelstand absichern
- Schwachstellenmanagement aufbauen: Vom Scan zur Behebung
