API Security
Rate limiting, input validation, CORS, schema validation, API keys vs OAuth
API security protects against abuse, data exfiltration, and exploitation of the dominant attack surface in modern applications. Core controls include authentication (OAuth 2.0 / API keys), authorisation (scopes, RBAC), rate limiting (prevent abuse and DoS), input validation (prevent injection), schema validation (OpenAPI contract enforcement), and CORS (cross-origin request control). The OWASP API Security Top 10 (2023) catalogues API-specific risks distinct from the web application Top 10.
Key Points
- OWASP API Security Top 10 2023: Broken Object Level Authorization (BOLA/IDOR), Broken Authentication, Broken Object Property Level Authorization, Unrestricted Resource Consumption, Broken Function Level Authorization, SSRF, Misconfigured Security (CORS, headers), Injection, Improper Inventory Management, Unsafe Consumption of APIs.
- BOLA (Broken Object Level Authorization) is the #1 API risk: `GET /api/orders/12345` — verify the authenticated user owns order 12345 on the server; never trust client-supplied resource IDs without ownership check.
- Rate limiting strategies: token bucket (steady burst allowance), fixed window (simple, vulnerable to burst at window edge), sliding window (smooth, Redis-based with sorted sets), leaky bucket (constant output rate) — implement at API Gateway + application layer.
- API rate limit headers: `X-RateLimit-Limit: 1000`, `X-RateLimit-Remaining: 950`, `X-RateLimit-Reset: 1716000000`, `Retry-After: 60` — return HTTP 429 on exhaustion; document limits in OpenAPI spec.
- CORS misconfiguration: `Access-Control-Allow-Origin: *` on authenticated APIs allows any website to make credentialed requests to your API from a user's browser — restrict to specific allowed origins.
- OpenAPI (Swagger) contract enforcement: use API Gateway request validation (AWS API Gateway model validation, Kong Request Validator plugin) to reject requests that do not match the schema before they reach the backend.
- API key vs OAuth token: API keys are simple (no expiry, no scope) — use for server-to-server integrations with static clients; OAuth tokens are scoped, short-lived, and support delegation — use for user-context API access.
- GraphQL-specific risks: introspection (disable in production to prevent schema enumeration), query depth/complexity limits (prevent expensive nested queries), field-level authorisation (each resolver must check permissions independently).
OpenAPI 3.0 spec: OAuth2 security, schema validation constraints, and rate-limit documentation
# OpenAPI 3.0 schema with security and rate-limit docs
openapi: "3.0.3"
info:
title: Payments API
version: "2.0"
security:
- BearerAuth: [payments:write]
paths:
/payments:
post:
summary: Create a payment
x-rate-limit: "100 req/min per user"
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentRequest'
responses:
'201': { description: Payment created }
'422': { description: Schema validation failed }
'429': { description: Rate limit exceeded }
components:
schemas:
PaymentRequest:
type: object
required: [amount, currency, recipient_id]
properties:
amount:
type: integer
minimum: 1
maximum: 1000000
currency:
type: string
pattern: '^[A-Z]{3}$'
recipient_id:
type: string
format: uuid
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWTReal-World Example
Stripe enforces API security through: OAuth 2.0 with narrow scopes (`payment_intents:write` not `all`), idempotency keys on all mutating endpoints, schema validation rejecting unexpected fields, rate limits of 100 RPS per secret key, and TLS 1.2+ with automatic cert rotation — a reference model for financial API security.