practice

Secure API Design

Building an interface where the safe path is the default and the unsafe one requires deliberate effort.

api-securityauthorisationtokensrate-limitingvalidation

Definition

Secure API design is the set of choices that make whole classes of vulnerability structurally impossible rather than merely discouraged.

The decisions that matter most

Authorisation on the object, not just the endpoint. The most common serious API vulnerability is an endpoint that checks the caller is authenticated but not that the requested object belongs to them. The structural fix is that data access goes through a layer that requires the caller's identity, so retrieving an object without an authorisation check is not expressible.

Deny by default. New endpoints are inaccessible until access is granted. The alternative produces an endpoint deployed without a policy, discovered by a scanner.

Short-lived tokens with narrow scopes, validated on every request — signature, expiry, audience, issuer. Long-lived API keys with full account access are the credential most often found in a public repository.

Never trust the client for anything that matters. Prices, quantities, permissions, identity and tenancy come from the server's state, not from the request body. A "price" field in a request is a design error.

Validate against a schema at the boundary, rejecting unknown fields rather than ignoring them — mass-assignment vulnerabilities are precisely the result of ignoring them.

Do not expose enumerable identifiers. Sequential IDs let an attacker walk the dataset once they find one authorisation gap, and they leak business volume.

Rate limit per client, per tenant and per endpoint, weighted by cost rather than count.

Fail closed on authorisation. If the authorisation service is unavailable, deny. This is the one place where graceful degradation is wrong.

Response hygiene

  • Errors that do not distinguish "not found" from "not yours", or you have built an enumeration oracle.
  • No stack traces or internal identifiers in responses.
  • Explicit field selection rather than serialising whole objects, so a new sensitive column does not silently appear in an API response.

Failure scenarios

  • Object-level authorisation missing on one of forty endpoints.
  • Authorisation only at the gateway, so anything reachable internally is unprotected.
  • A token with no audience check, accepted by a service it was not issued for.
  • Verbose validation errors confirming which accounts exist.
  • A new field added to a shared serialiser, exposing data through every endpoint that uses it.

Interview question

"How would you make it structurally impossible to add an endpoint that returns another tenant's data?"