Overview

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.
CH12 F01 lauret3
API security is a concern throughout the design process, impacting capabilities identification, HTTP representation, data modeling, and describing the API with OpenAPI.
CH12 F02 lauret3
Card, holder, and transaction sensitive data become less sensitive by removing or encrypting data.
CH12 F03 lauret3
An update based on outdated data corrupts data.
CH12 F04 lauret3
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.
CH12 F05 lauret3
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.
CH12 F06 lauret3
Scopes are usually handled at the API gateway level, while the implementation handles user permission.
CH12 F07 lauret3
Scopes are visible to providers and consumers, but also end users.
CH12 F08 lauret3
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.
CH12 F09 lauret3
Define scopes in security schemes under components.securitySchemes. You can define multiple security schemes to organize scopes.
CH12 F10 lauret3
The security list contains the security schemes and scopes a consumer needs to use to access an operation.
CH12 F11 lauret3
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.
CH12 F12 lauret3
An unexpected server error must not disclose implementation details. Return generic information with an optional reference of this error’s occurrence for further investigation.
CH12 F13 lauret3
Each response description provides information that is essential for the implementation. The response description is different from the actual error message.
CH12 F14 lauret3
The UnexpectedError schema precisely describes what is expected on 500 errors, which avoids disclosing sensitive information.
CH12 F15 lauret3

FAQ

What are the key security steps during an API call? - Use HTTPS/TLS to encrypt transport between consumer and provider. - Authenticate and authorize the calling application (and end user, if any) via an access token that carries identity and scopes/permissions (e.g., OAuth 2.0/OpenID Connect). - Enforce business/context rules in the implementation using the token’s claims: allow only permitted operations and data for that app/user, then execute accordingly.
Which design mistakes most often create API vulnerabilities? - Overexposing data or operations (e.g., returning internal prices, verbose errors). - Delegating business logic to clients (risking inconsistent or corrupt state). - Missing object-level authorization checks (user can access another user’s resources). - Data integrity gaps (concurrent updates, replayed requests). - Protocol/architecture leaks (sensitive data in URLs, logs). - Coarse or unclear scopes that grant unnecessary access. - Poorly documented security expectations in OpenAPI.
How do I minimize API surface and decide what to expose? - Challenge necessity of every operation and field (sensitive and non-sensitive). - Remove or reduce sensitivity (mask PAN to last 4 digits, drop unnecessary PII, categorize instead of precise values, consider privacy-preserving techniques). - Split mixed-sensitivity operations into separate ones. - Isolate sensitive/admin capabilities in dedicated APIs. - Align with security/legal stakeholders’ guidance; keep the OpenAPI spec exhaustive.
How should I handle sensitive search filters and identifiers in URLs? - Never put sensitive data in URLs (they get logged and cached widely). - Use POST /resources/search with filters in the request body instead of query parameters. - If external IDs (e.g., SSN) are sensitive, search by them via POST /search to obtain an internal, non-sensitive ID, and then use that ID in subsequent paths.
How can I ensure operations behave correctly for each app and end user? - Document in OpenAPI who can see/do what (operation/response/property descriptions). - State list/search filtering rules explicitly (e.g., “returns only accounts owned by the user”). - Explain how inputs constrain access (e.g., source account must belong to the caller’s user). - Consider design that narrows access (e.g., GET /owners/{ownerId}/sources, support me shorthand). - Coordinate 403 vs 404 responses based on whether the existence can be disclosed.
How do I protect data integrity (concurrency, duplicates, replays)? - Use HTTP semantics correctly: GET is safe; PUT/DELETE idempotent; POST/PATCH are not. - Prevent replays with an idempotency key header and/or business-level deduplication windows. - Make updates conditional: return ETag (or Last-Modified) on reads and require If-Match (or If-Unmodified-Since) on PUT/PATCH; return 412 if stale.
What can still leak even over HTTPS, and how do I mitigate it? - URLs (paths and queries) and sometimes bodies may be logged by gateways, proxies, servers, and clients. - Avoid sensitive data in URLs altogether; keep it in bodies. - Assume consumer-side environments (e.g., mobile, partners) are untrusted. - Encrypt or sign payloads where needed; design and document what parts are protected.
When should I encrypt or sign payloads, and what must I document? - Decide with security experts whether to protect the whole message or selected fields, and whether it varies by consumer. - Document algorithms/keys/exchange processes (out-of-band or via API), what’s encrypted or signed, and how validation happens. - Consider standards such as HTTP Message Signatures, encrypted content encoding, and JOSE (JWE/JWT). - Reflect any conditional behavior (e.g., per-scope) in operation/property descriptions.
What are scopes, and how do I design them for least privilege? - Scopes limit which operations an app can call; permissions/roles in the token govern what the end user can do. - Design options (often combined): - Operation-based (fine-grained). - Resource/concept-based. - Use-case-based (cover all steps). - Read vs write. - User/consumer-based (e.g., owner vs advisor, first-party vs third-party). - Behavior-tweaking (e.g., include sensitive fields only if scope present). - Name and describe scopes clearly; avoid catch-all “write” scopes that include sensitive actions.
How do I return security errors safely and specify them in OpenAPI? - 401 Unauthorized for missing/invalid/expired token. - 403 Forbidden when the issue is fixable (missing scope/permission) and existence can be disclosed; otherwise 404 Not Found. - 500 Internal Server Error must not leak stack traces, server names, IPs, or DB info; return a generic message plus an opaque reference ID. - In OpenAPI, write precise response descriptions (don’t use only status text); define error schemas (e.g., problem+json) using JSON Schema to constrain title, detail, and fields and prevent accidental data leaks.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Design of Web APIs, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Design of Web APIs, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Design of Web APIs, Second Edition ebook for free