12 Designing a secure API
API security is integral to good API design, not an afterthought. As APIs become prime attack vectors, designers must help reduce risk by shaping interfaces that expose only what is necessary, behave correctly under varying contexts, and prevent data leakage or corruption. This chapter positions security as a design-layer responsibility throughout the lifecycle, showing how thoughtful choices about resources, operations, data models, and documentation (notably with OpenAPI) materially influence resilience. It frames a practical path: minimize the surface, enforce context-aware behavior, preserve data integrity, avoid protocol- or architecture-driven leaks, partition access with scopes, and return errors that are useful yet never revealing.
Minimizing the surface begins by identifying sensitive data and critical operations, then challenging their presence, reducing or masking what’s shared, splitting mixed-sensitivity actions, or isolating sensitive capabilities into dedicated APIs. Designers should specify who may see or do what and, where helpful, narrow access paths by design. Integrity requires faithful use of HTTP semantics (recognizing safe and idempotent methods), replay defenses (idempotency keys and business de-duplication), and conditional updates (for example, with entity tags and preconditions) to prevent overwrites based on stale reads. To avoid protocol or architectural leaks, never place sensitive elements in URLs; move filters to request bodies with dedicated search endpoints, use non-sensitive internal identifiers and map from sensitive ones via searches, and, when needed, integrate payload encryption or signatures. All such expectations belong in the interface contract so implementers can enforce them consistently.
Scopes apply least-privilege at the consumer level and must be designed to be both precise and understandable. Options include operation-based scopes, broader resource or use-case scopes, read/write separation, end-user or consumer-specific groupings, and behavior-tweaking scopes that adjust returned data. Gateways typically enforce scope access to operations, while implementations enforce end-user permissions and business rules; both sides rely on clear OpenAPI descriptions that define and attach scopes to operations. Finally, error handling should be explicit and safe: use 401 for token issues, 403 when missing scopes or permissions can be remedied, and 404 when existence must not be disclosed; keep 500 responses generic and free of implementation details, ideally constrained by schemas to prevent accidental leaks. Together, these practices make security a first-class design outcome rather than a patch applied later.
The Shopping Website gets an access token to call the Shopping API to retrieve an end user’s orders. Based on the token, the Shopping API implementation verifies the consumer has appropriate permissions before returning the user’s data.
API security is a concern throughout the design process, impacting capabilities identification, HTTP representation, data modeling, and describing the API with OpenAPI.
Card, holder, and transaction sensitive data become less sensitive by removing or encrypting data.
An update based on outdated data corrupts data.
By returning the resource data version in an Etag header upon reading, we can condition updates with the If-Match header and ensure data stays uncorrupted.
HTTPS secures communication between client and server. URL and even body can be logged in many places on the consumer and provider sides. How security is handled on the consumer side is unknown.
Scopes are usually handled at the API gateway level, while the implementation handles user permission.
Scopes are visible to providers and consumers, but also end users.
Choose scope design options according to your context. You can use multiple options in the same API and also combine them to refine coarse-grained scopes. Behavioral scopes may apply to one or more operations.
Define scopes in security schemes under components.securitySchemes. You can define multiple security schemes to organize scopes.
The security list contains the security schemes and scopes a consumer needs to use to access an operation.
The Read an account operation returns 403 if the consumer hasn’t the proper scope or if the end user is a bank advisor who doesn’t manage the account. It also returns 404 if the end user is an account owner who does not own the account.
An unexpected server error must not disclose implementation details. Return generic information with an optional reference of this error’s occurrence for further investigation.
Each response description provides information that is essential for the implementation. The response description is different from the actual error message.
The UnexpectedError schema precisely describes what is expected on 500 errors, which avoids disclosing sensitive information.
The Design of Web APIs, Second Edition ebook for free