Authentication

Authentication is the first line of API defence. Every request to a non-public endpoint must be authenticated before any processing occurs.

  • Use OAuth 2.0 / OIDC for user-facing APIs. Do not implement custom authentication schemes. Use proven libraries and frameworks.
  • Use short-lived JWT tokens. Access tokens should expire in 15–60 minutes. Use refresh tokens for session persistence.
  • Validate JWT signatures and claims. Verify alg, iss, aud, exp, and nbf. Reject tokens with alg: none.
  • Use API keys for machine-to-machine. Scope keys to the minimum required permissions. Rotate on a schedule.
  • Implement MFA for sensitive operations. Privileged actions (deleting accounts, changing billing, exporting data) should require step-up authentication.
  • Do not pass credentials in URLs. API keys in query parameters appear in server logs, browser history, and proxy logs.
HTTP request — correct credential placementHTTP
# Correct: credential in Authorization header
GET /api/v1/users HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...

# Wrong: credential in URL (never do this)
GET /api/v1/users?api_key=sk_live_abc123 HTTP/1.1

Authorisation

Authentication proves who the caller is. Authorisation determines what they can do. Broken object level authorisation (BOLA) — the most common API vulnerability — happens when authorisation is skipped or applied inconsistently.

  • Check authorisation on every request, every endpoint. Do not assume a user authenticated at one endpoint has permission for all others.
  • Validate object ownership. When a user requests /api/orders/12345, verify that order 12345 belongs to the authenticated user — not just that the user is authenticated.
  • Use policy-based access control (PBAC) or RBAC. Centralise authorisation logic rather than scattering if user.role == "admin" checks throughout the codebase.
  • Apply function-level authorisation. Admin endpoints must require admin credentials — not just any valid authentication token.
  • Enforce authorisation at the API layer, not the UI layer. Front-end hiding of buttons is not security. Test every API endpoint directly.

BOLA is OWASP API1:2023: It is the most exploited API vulnerability. An attacker simply changes an ID in a request and accesses another user's data. Always validate object ownership server-side.

Input validation

Every value that crosses the API boundary — request body, path parameters, query strings, headers — is untrusted input. Validate all of it.

  • Define and enforce a schema for every endpoint. Use OpenAPI/Swagger to define expected types, formats, and constraints. Validate incoming requests against the schema automatically.
  • Reject unexpected fields. Do not silently ignore extra fields. This prevents mass assignment vulnerabilities where attackers set fields like isAdmin: true.
  • Validate data types and ranges. An age field should accept only positive integers within a sane range — not arbitrary strings.
  • Sanitise string inputs. Strip or encode HTML, SQL metacharacters, and shell metacharacters before use in queries, commands, or output.
  • Validate file uploads. Check MIME type, file extension, and file content (not just the header). Scan uploaded files for malware.
  • Limit payload size. Set maximum request body sizes. Unvalidated large payloads can cause DoS or memory exhaustion.

Rate limiting and throttling

Without rate limiting, your API is open to brute force attacks, credential stuffing, data scraping, and resource exhaustion. Rate limiting is not optional.

  • Apply rate limits per client. Limit by API key, user ID, or IP address. Global rate limits are easier to bypass.
  • Rate limit authentication endpoints aggressively. Login, password reset, and OTP verification endpoints are the primary targets for brute force. Apply strict limits and account lockouts.
  • Return 429 Too Many Requests with Retry-After. Give clients the information they need to back off correctly.
  • Apply business logic rate limits. Limits should reflect what a legitimate user could plausibly do — not just technical API throughput.
  • Implement exponential backoff. Repeated violations should result in exponentially increasing cooldown periods.
Rate limit response headersHTTP
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711411200
Retry-After: 60

Transport security

  • TLS 1.2 minimum, TLS 1.3 preferred. Disable SSL 3.0, TLS 1.0, and TLS 1.1.
  • HTTPS everywhere, no HTTP fallback. Redirect HTTP to HTTPS at the infrastructure level. Use HSTS.
  • Use strong cipher suites. Disable RC4, DES, 3DES, and export-grade ciphers. Prefer forward-secrecy ciphers (ECDHE).
  • Validate TLS certificates in all clients. Never disable certificate validation in production code. verify=False in Python requests or rejectUnauthorized: false in Node.js is a critical vulnerability.
  • Certificate pinning for high-value mobile clients. For apps with sensitive data, pin the certificate to prevent MITM via rogue CAs.

Error handling

Error messages are a reconnaissance tool. Verbose errors expose stack traces, library versions, database query structures, internal paths, and server configuration.

  • Return generic error messages to clients. Log the full error server-side but return only a safe, generic message externally.
  • Use consistent error response schemas. Every error should follow the same structure. Inconsistency can reveal which code path executed.
  • Include a correlation ID in errors. Give clients a reference they can share with support without exposing internal details.
  • Do not expose stack traces in production. Disable debug mode and verbose error pages in all non-development environments.
  • Handle all exceptions. Unhandled exceptions often result in framework default error pages that expose server technology details.

Logging and monitoring

  • Log all authentication events. Successful logins, failed logins, token issuance, and token revocation.
  • Log access to sensitive resources. Who accessed what, when, from where.
  • Do not log sensitive data. Never log passwords, tokens, full card numbers, or other PII in plaintext.
  • Alert on anomalous patterns. Sudden spikes in 401/403 responses, access from unexpected geolocations, mass data retrieval — all warrant automated alerting.
  • Centralise and protect logs. Ship logs to a SIEM. Ensure logs cannot be tampered with by a compromised application server.

OWASP API Security Top 10 — quick reference

OWASP API Security Top 10 (2023)text
API1:2023  Broken Object Level Authorization (BOLA)
API2:2023  Broken Authentication
API3:2023  Broken Object Property Level Authorization
API4:2023  Unrestricted Resource Consumption
API5:2023  Broken Function Level Authorization
API6:2023  Unrestricted Access to Sensitive Business Flows
API7:2023  Server Side Request Forgery (SSRF)
API8:2023  Security Misconfiguration
API9:2023  Improper Inventory Management
API10:2023 Unsafe Consumption of APIs

Quick checklist

  • All endpoints require authentication (unless explicitly public)
  • Object ownership validated on every request involving user data
  • OpenAPI schema defined and validated for all endpoints
  • Rate limiting applied to all endpoints, strict on auth endpoints
  • TLS 1.2+ enforced, HSTS enabled, no HTTP fallback
  • Generic error messages returned; full errors logged server-side only
  • All auth events and sensitive resource access logged
  • No sensitive data (tokens, passwords) in URLs or logs
  • DAST scan run against staging environment before every release
  • API inventory maintained — no shadow or zombie APIs

The rule of zero trust: Treat every API caller as a potential adversary until proven otherwise. Validate everything, log everything, and assume your defences will be tested.

Test your APIs against the OWASP Top 10

AquilaX DAST automatically crawls and attacks your APIs to find authentication flaws, BOLA, injection, and misconfigurations — before attackers do.

Start API security testing →