System Design · Security
API security
A partner script, a mobile app, or a scraper hits your checkout and search endpoints all day. Unlike a tired human, an never sleeps. So rare bugs become daily events at scale.
Defense stacks identity, object-level authorization, , and audit logs so abuse shows up as metrics, not angry tweets.
Request defense journey
Validate schema
Reject malformed bodies early.
Login is not ownership.
Meter by route cost and tenant.
Observe decisions
Audit allow/deny with correlation ids.
What actually happens
Every request should pass a cost funnel: reject garbage, authenticate cheaply, authorize per object, meter expensive routes, emit decision logs. and are classic input bugs; is the business-logic cousin where IDs are guessed after login.
Browsers add and subtleties around cookies. Partners need API key hygiene and request signing for webhooks. Login magnets attract ; URL features risk into cloud metadata.
Transport security (, TLS posture, ) pairs with application integrity. At millions of users, counters and audit streams are production data systems: size them like product features.
Try it: funnel an API request through defensive gates
Each gate has a job: reject garbage, bind identity, enforce object ownership, meter cost, then log the decision. Login alone never implies access to an id in the URL.
- Stage
- 0 / 6
- Outcome
- In progress
- Rate tokens
- 5
- Request type
- valid
- 1Schema validation
- 2Authentication
- 3Object authorization
- 4Rate limit
- 5Handler
- 6Audit log
Input trust
400 earlyOpenAPI or JSON schema plus maximum body size.
Identity + object
BOLAAuthenticated tenant must match resource ownership for the action.
Cost + evidence
429 + logToken bucket per client and route; audit every allow and deny.
Advance a partner API call through validation, authentication, object checks, rate limiting, and audit. Malformed bodies stop early; wrong owner stops at authorization.
Early reject. Schema and size validation save authz CPU and keep error shapes safe for clients.
Object checks. Handlers must verify tenant and action on every id, not only on session creation.
How to choose API hardening moves
1. Treat every endpoint as public. Authz checks belong in handlers, not route comments.
2. Prefer positive validation. Schemas beat chasing bad inputs with regex alone.
3. Meter by cost, not vanity RPS. Login, export, and admin mutations need different buckets and over-budget responses.
Simple rule of thumb
Validate ruthlessly, authorize per resource, throttle economically, sign critical webhooks, and instrument everything: attackers script faster than humans can grep logs.
In simple terms: never trust the body, never trust the id in the URL, and make abuse expensive.
API abuse defense pipeline
Validate, authorize, throttle, and observe before business logic pays the cost
Client request
CDN and WAF
API gateway
Schema validation
Authn and authz
Route and tenant rate limits
Service handler
Database or queue
Side path from gateway
Abuse detection
Challenge, block, or slow path
Observability
Audit stream (from auth + limits)
Validate
A request schema defines allowed types, required fields, ranges, formats, and size limits before business logic executes. Validate relationships too: an end date before a start date can be syntactically valid but meaningless. Reject or explicitly handle unknown mutation fields so a caller cannot set internal properties such as role or approved status. Continue using parameterized database queries; input validation is not a substitute for separating data from executable query structure.
Authorize
Authorize the action against the actual resource and tenant on every protected read or mutation. For GET /orders/123, a valid token proves a caller identity, but the server must still determine whether that caller may read order 123. Apply the same rule to batch endpoints, exports, nested resources, and derived caches. Replacing sequential IDs with random IDs reduces guessing but does not create authorization.
Throttle
Bucket by IP, key, user, tenant, route, and expensive operation class.
Observe
Emit allow/deny decisions, correlation IDs, and abuse reasons for response.
API threat model card
- Assets
- Tokens, tenant data, admin routes, export jobs, webhooks.
- Actors
- Valid users, partners, scrapers, bots, stolen API keys.
- Trust boundaries
- Edge, gateway, service handler, database, audit stream.
- Attack paths
- Injection, BOLA, replay, mass assignment, scraping, credential stuffing.
- Controls
- Schema validation, object authorization, request signing, route quotas.
- Detection
- Deny spikes, bulk reads, token reuse, abnormal endpoint mix.
- Residual risk
- Valid clients can still abuse business flows until anomaly rules and quotas catch up.
Injection & XSS defenses
Stop trusting strings from the internet
SQL injection: database commands hidden in user input
If you glue user strings into SQL text, the database cannot tell data from instructions. A crafted userId becomes extra clauses:DROP TABLE, bulk exfiltration, or bypassing login checks.
Risky concatenation
query = "SELECT * FROM users WHERE id = " + userId // userId = "1; DROP TABLE users; --"
Parameterized query
query = "SELECT * FROM users WHERE id = $1" params = [userId]
Add defense-in-depth: least-privilege DB roles (no DDL from app users), Web Application Firewall rules for obvious probes, and centralized DB gateways so risky queries surface in one audit stream.
XSS: Cross-Site Scripting (scripts running in someone else’s browser)
Reflective XSS bounces attacker input straight back in HTML; stored XSS saves it in comments/profiles; DOM XSS mutates the page client-side. All share one goal: execute JS with the victim’s cookies/tokens in scope for your site’s origin.
- Encode by context (HTML body vs attribute vs URL): generic “strip tags” often misses edge cases.
- CSP tells the browser which script origins are legitimate: inline handlers become harder to abuse.
- HttpOnly cookies keep session IDs out of document.cookie so XSS cannot trivially exfiltrate them to attacker.com (still fight XSS: HttpOnly is not a full substitute).
Security headers: what they actually do
- Content-Security-Policy (CSP)
- Browser allow-list for scripts/styles/images: shrinks XSS blast radius when HTML slips through.
- X-Content-Type-Options: nosniff
- Stops browsers from “sniffing” uploads as executable when MIME types lie.
- X-Frame-Options / frame-ancestors
- Reduces clickjacking: embedding your app in invisible iframes on evil sites.
- Strict-Transport-Security (HSTS)
- Forces HTTPS for a period: cuts sslstrip-style downgrade tricks (combine with redirects + preload carefully).
Input validation: treat the body as untrusted wire format
Validation is not “regex everything”. It is rejecting whole objects that do not match a schema: wrong types, surprise fields, absurd lengths, or mismatched Content-Type. Fail closed before business logic runs.
- Schema-first: OpenAPI/JSON Schema/protobuf: generate validators and docs from one source.
- Deny extras: unknown JSON keys often hide prototype pollution or mass-assignment bugs.
- Size caps: stream large uploads or reject early: prevents memory bombs before parsing.
- Charset / Content-Type: reject ambiguous combinations that confuse parsers.
CORS & CSRF
Origin controls + cookie/session semantics
CORS allowlists: who may read responses from the browser
Browsers send an Origin header on cross-site fetches. Your API decides whether to expose responses to that origin via Access-Control-Allow-Origin. Preflight OPTIONS requests ask permission before non-simple verbs or custom headers.
Server-side allowlist pattern
- Echo Access-Control-Allow-Origin only for known hosts, never reflect arbitrary Origin strings from attackers.
- Tighten Allow-Methods / Allow-Headers; cache preflight only as long as policies stay stable.
CSRF defenses: stop forged requests that reuse cookies
Cookie-based sessions
Attacker sites cannot read your HttpOnly cookie, but they can cause the browser to POST with it: mitigate with synchronizer tokens, SameSite cookies, or custom headers that simple forms cannot forge cross-origin. Choose defenses according to how credentials are sent. A cookie is attached by the browser under its cookie rules, so a state-changing endpoint should validate the application’s CSRF protection and expected origin as appropriate. CORS controls which cross-origin scripts can read responses and make certain requests; it is not a general authentication mechanism, and simple cross-origin requests can still reach a server.
- Synchronizer tokens in forms or X-CSRF-Token headers.
- SameSite=Lax/Strict reduces cookie inclusion on cross-site POSTs (not a solo fix for every flow).
- Double-submit cookie patterns when you cannot keep server session state.
Bearer tokens in memory / headers
Random evil sites cannot attach arbitrary Authorization headers to your API domain: CSRF pressure drops. Pressure shifts to XSS stealing tokens from JS-accessible storage: prefer short TTL + CSP + minimized inline scripts.
API keys & request signing
Integrity + replay resistance
API key hygiene: static secrets that must leak badly when mishandled
Keys are convenient for scripts and partners, also trivial to paste into developer platform. Assume periodic leaks; design for fast revocation, scoped permissions, and per-key observability (who rotated what, when).
- Generate cryptographically random strings; store only hashes at rest where possible.
- Prefix keys (sk_live_) so scanners and humans spot leaks quickly.
- Scope + expire + rotate with overlapping validity windows.
- Throttle per key: IPs rotate; stolen keys do not.
HMAC request signing: tamper-evident HTTP without TLS alone
Useful when proxies terminate TLS early, when replay windows must be seconds, not minutes, or when webhooks must prove they originated from trusted senders Pair signatures with clock-skew limits and idempotency keys for POST retries.
Canonical string (illustrative)
payload = HTTP_METHOD + PATH + TIMESTAMP + HASH(body)
signature = HMAC_SHA256(secret, payload)
- Reject timestamps outside tight skew windows: stops replay of captured requests.
- Recompute MAC with server-held secret; compare in constant time: timing leaks recover bytes slowly but surely.
- Rotate signing secrets with overlap; dual-verify during migrations.
Real systems add canonical header ordering, region, and service names: copy a reviewed request-signing profile instead of inventing one during a feature sprint. A signature protects only the bytes and context included in its verified input. Verify the received raw body using the sender’s documented canonicalization before transforming it. Then check a bounded timestamp and a durable event ID so a valid old message cannot be replayed indefinitely. A correct webhook signature proves origin and integrity; business deduplication still determines whether the event’s effect has already happened.
Application-layer encryption, beyond HTTPS on the wire
TLS hides bytes from network taps but not necessarily from compromised proxies, log pipelines, or analysts with DB access. Encrypt PII fields before they hit queues, warehouses, or third-party tools: typically with envelope encryption (DEK per record, KEK in managed key service) so you can rotate without rewriting petabytes blindly.
Rate limiting & abuse workflows
Progressive responses beat naive scale-out
Layered throttles
Cheap edges absorb brute noise; gateways enforce business fairness; databases stay for queries that already passed identity checks, never rely on a single global IP limit for IPv6-heavy mobile networks.
- Edge / CDN buckets per ASN or IP + anomaly detection.
- API key + user ceilings with different burst allowances.
- Stricter buckets on auth, exports, search: anything $O(n)$ or fan-out heavy.
Standard rate-limit headers
Return a clear status and retry policy when a quota is exceeded so cooperative clients can back off. State whether a quota counts requests, concurrent work, or weighted cost, and identify the relevant scope without exposing sensitive internal details. A retry hint is not a reservation of future capacity. Clients should combine it with jitter, an end-to-end deadline, and safe retry semantics.
- X-RateLimit-Limit
- Max tokens per window
- X-RateLimit-Remaining
- Tokens left in current window
- Retry-After
- Seconds (or HTTP-date) to wait after 429
Adaptive tightening: dynamic quotas from risk signals
Tie limits to error rates, CAPTCHA outcomes, or bot scores, when abuse spikes, shrink quotas automatically and alert humans. Document automation so on-call engineers know whether tightening came from policy code vs incidents.
Pair with graceful degradation: serve stale reads or queues instead of burning CPU chasing attackers through expensive joins.
Credential stuffing playbook: login is the magnet for bots
- Tight per-IP and per-account velocity; exponential backoff after failures, never identical JSON errors that distinguish valid emails (account enumeration risk).
- Step-up MFA / email challenges when geography or device posture changes sharply.
- Notify users of new devices; integrate breached-password datasets with care for privacy and false positives.
- Instrument distinct metrics: failure ratio, credential pairs tried, ASNs: stuffing often clusters before password-spray rotates.
| Endpoint | Normal RPS | Burst cap | Cost/request | Limit key | Over budget |
|---|---|---|---|---|---|
| Login | 2k | 5k | Password hash + risk lookup | IP + account + device | Step-up or slow path |
| Search | 8k | 12k | Index fan-out | Tenant + user + route | Return 429 with backoff |
| Export | 200 | 400 | Queue + storage write | Tenant + job type | Queue or require approval |
| Webhook ingest | 10k | 20k | Signature + idempotency write | Partner key | Retry-After and dead-letter |
| Admin mutation | 50 | 100 | Policy + audit | Admin user + tenant | Deny and alert |
Rate limit memory & audit volume
Scale answer: counters and logs are production data systems, not side effects
Counter memory sizing
A token bucket needs a key, token count, refill timestamp, TTL, and metadata. Budget roughly 80-160 bytes per active bucket before datastore overhead.
- 10M active identities × 4 buckets × 128 B ≈ 5.1 GB raw; replicas, indexes, and fragmentation can push this several times higher.
- 20M active keys × 5 counters/key × 24 B/counter × 3 windows × 2 replicas ≈ 14.4 GB before key strings, TTL metadata, and allocator overhead.
- Separate cheap edge counters from expensive account/tenant counters so bot IP churn does not evict customer state.
- Use approximate structures for massive low-value dimensions; keep exact counters for billing, auth, and abuse decisions.
Audit logging volume
At 50k protected requests/sec and 800 bytes per structured decision log, raw ingest is ~40 MB/sec, or ~3.5 TB/day before compression and replicas.
- At 80k RPS, 1.2 events/request, and 900 bytes/event, audit ingest is ~86.4 MB/sec, or ~7.5 TB/day raw before compression and replicas.
- Log every authz deny, admin action, token rotation, and sensitive data read; sample routine low-risk allows only if policy permits.
- Keep correlation IDs, actor, tenant, route, decision, reason, and latency; avoid raw secrets or sensitive payloads.
- Plan retention tiers: hot search for incidents, cold immutable storage for audits, deletion workflows for policy-bound data.
Abuse prevention at millions of users
Explain the abuse path as a cost funnel: reject malformed input, authenticate cheaply, authorize per object, meter by route cost, emit decision logs, and degrade non-critical work. The winning answer protects scarce resources while preserving good-user paths.
Testing and runbook panel
- Replay object-authorization tests for every role, tenant, bulk endpoint, nested resource, and indirect object reference.
- Load-test rate-limit counters with realistic key cardinality, hot keys, retry storms, and eviction pressure.
- During abuse spikes, move from observe to slow path, challenge, route clamp, tenant quota clamp, then temporary block with audit reason.
- Verify audit queries can answer: who touched this resource, from where, under which policy version, and why was the request allowed?
API risk themes & audit logging
Business-logic abuse is still abuse
OWASP API Security Top 10: map each risk to a control
- API1 Broken Object Level Authorization (BOLA): authorize every object id: /orders/{id} must prove ownership, not only login.
- API2 Broken Authentication: validate JWT iss/aud/exp, rotate refresh, step-up MFA on sensitive mutations.
- API3 Broken Object Property Level Authorization: deny mass-assignment of role, price, is_admin fields.
- API4 Unrestricted Resource Consumption: pagination caps, GraphQL cost limits, export quotas: meter expensive routes.
- API5 Broken Function Level Authorization: hide admin routes behind role-matrix tests; never rely on obscurity.
- API6 Unrestricted Access to Sensitive Business Flows: coupon stacking, ticket bots: domain monitors + progressive friction.
- API7 Server Side Request Forgery: allowlist URL fetch schemes/hosts; block link-local/metadata ranges.
- API8 Security Misconfiguration: CORS credentials + wildcard Origin, verbose errors, open admin debug.
- API9 Improper Inventory Management: shadow APIs, old versions still live: inventory + sunset telemetry.
- API10 Unsafe Consumption of APIs: validate third-party payloads; do not trust partner JSON more than user input.
Audit telemetry: what “good” looks like
Structured JSON logs with timestamp, actor, actor type, tenant, resource hash, action, decision, policy version, reason, request ID, source network class, client hints, latency, and risk score. Stream to immutable storage for tamper resistance.
- Retention aligns with audit and privacy requirements: legal holds override TTL automation.
- PII minimization: log stable pseudonyms, not raw PAN or health payloads.
- Alert on deny spikes, impossible admin geography, or bulk exports outside business hours.
TLS posture & pinning
Mobile + service meshes
Certificate pinning: trust fewer CAs than the whole global bundle
Embed SPKI hashes of your leaf or intermediate cert in mobile binaries; on mismatch, fail closed and report telemetry (users cannot easily bypass like curl -k). Ship at least one backup pin before rotating primaries. Otherwise app stores brick until emergency releases.
Production TLS profile: baseline hygiene checklist
- Protocols: TLS 1.2 minimum: prefer 1.3; disable legacy SSL/TLS with known breaks.
- Ciphers: AEAD suites (AES-GCM, ChaCha20-Poly1305); prioritize ECDHE for forward secrecy.
- Certificates: automate issuance/renewal (certificate automation); monitor expiry SLOs; enable OCSP stapling where supported.
- Internal RPC: mesh-managed mTLS: policy binds identities to namespaces/service accounts, not just cluster IPs.
Case studies
Public breaches reinterpreted as API lessons: patching, authz, and SSRF chains
Credit bureau · 2017
Credit bureau breach: known vuln, overdue patching, massive structured-data leak
Attackers hit an internet-facing application teams had failed to patch in time, then moved sideways into databases holding structured consumer records: credit histories usable for fraud for years.
Beginners should anchor on process failure as much as “evil hacker”: without authoritative inventories and patching SLAs, even mature SIEM deployments chase ghosts post facto.
Simplified attack / failure chain
- Scanner identifies vulnerable framework-equivalent surface reachable from internet.
- Exploit establishes foothold on app subnet lacking segmentation depth.
- Credential harvesting yields broader DB/API credentials scoped wider than least-privilege.
- Bulk queries blend until downstream fraud peaks expose latency.
Advanced controls & design pressure
- Weekly automated discovery mapping DNS ↔ workloads ↔ owners; escalate orphans weekly.
- WAF/virtual patch lanes documented as stop-gap hours, not parity with real code fixes.
- Columnar encryption + managed key service policies limit insider/export misuse even behind VPN.
- Immutable audit answering “which service principal queried >1M rows?” inside analyst SLA.
- Segment vault subnets: jump hosts + session recording for humans touching bulk tables.
Aftermath, signals & interview questions
Multi-billion-dollar remediation; disclosure timelines tightened globally.
- Interview: “Who owns vulnerability aging for internet-facing apps?”: demand named roles.
- Dashboard: mean patch age by severity vs EPSS scores.
Cloud SSRF · IAM roles
Cloud metadata SSRF archetype: metadata service to excessive IAM to bucket exfiltration
A misconfigured web/WAF configuration allowed attackers to coerce the server into fetching attacker-chosen URLs, including cloud metadata endpoints that mint temporary IAM credentials for attached roles.
Beginners: SSRF is “the server becomes my browser inside your VPC.” APIs that accept URLs or forward webhooks are frequent injection points: TLS does not help once your own server trusts internal IP ranges.
Simplified attack / failure chain
- Attacker supplies SSRF payload targeting link-local metadata URL.
- Server retrieves ephemeral credentials scoped to over-privileged instance profile.
- ListBuckets / sync tooling enumerates buckets and stages multi-GB archives.
- Exfiltration blends until object-level alerts fire: often late without baseline anomaly ML.
Advanced controls & design pressure
- IMDSv2 + hop limits + deny-by-default egress; separate NAT paths per tier.
- Narrow IAM with ABAC/resource prefixes; forbid wildcard admin on web roles.
- URL parsers allow-list schemes and hosts; block redirects to internal ranges.
- VPC endpoints + PrivateLink reduce metadata exposure patterns, still validate apps.
- managed key service-backed bucket policies requiring encryption context per tenant.
Aftermath, signals & interview questions
- Federal prosecution underscored insider-like blast radius from SSRF, not “only” XSS severity.
- Mock interview: draw packet path from ALB → app pod → metadata hop limit.
Social API · IDOR class
partner-data misuse era: consent vs authorized data surfaces
Third-party personality quizzes rode OAuth grants that effectively exported friend-graph-scale datasets: many users understood “this app sees my quiz,” not “this app harvests my entire social neighborhood.”
Beginners internalize that scopes describe mechanics, not morality: product/legal review must gate bulk derivative datasets regardless of token validity.
Simplified attack / failure chain
- Bootstrap OAuth consent with narrow wording but broad backend joins.
- Background jobs fan out multi-hop graph pulls via poorly capped batch endpoints.
- Researchers/partners export aggregates into analytic warehouses lacking row audit.
- Public backlash triggers retroactive API restrictions: breaking legitimate researchers too.
Advanced controls & design pressure
- Per-app QPS + cardinality budgets on graph expansions; kill-switch tokens centrally.
- Differential privacy budgets per integration with accountant tooling.
- Immutable audit of large pulls: correlation IDs tying analysts to datasets.
- Sunset APIs with compile-time flags in SDKs + runtime telemetry on zombie usage.
- Red-team “partner onboarding” flows quarterly: often softer than consumer flows.
Aftermath, signals & interview questions
privacy-law momentum; platforms tightened developer verification: interviews now expect answers on data minimization vs growth hacking tension.
Mobile/web parity · scraping
sequential-ID scraping narratives: sequential IDs + weak authz ⇒ bulk harvest
Services exposing monotonic IDs without object-level authorization enabled scrapers to iterate URLs like /posts/1..N at wire speed: often faster than product teams assumed because CDNs cached public-ish responses.
Beginners: login proves identity; authorization must prove row entitlement every call, especially for mobile APIs mirrored naïvely from web HTML assumptions. Enforce tenant scope when loading the record, not only after serializing a response or generating a download link. Background workers and service-to-service calls also need trusted authorization context. Test both allowed and denied cases, including a valid user who changes only the object ID. These tests catch a missing boundary that an authentication-only happy-path test cannot see.
Simplified attack / failure chain
- Attacker harvests bearer token from poorly pinned mobile binary or leaked admin creds.
- Parallel workers sweep ID ranges with minimal backoff: 429 absent.
- Dataset replayed offline for OSINT / harassment workflows.
- Infra bills spike; fraud teams notice odd geographic fan-out.
Advanced controls & design pressure
- Opaque IDs + MAC’d capability URLs where enumeration matters.
- Adaptive rate limits per tenant + progressive latency penalties (“tar pit”).
- GraphQL cost limits, persisted queries, field-level authz in resolvers, not only gateway auth.
- Honeypot IDs triggering SOC automation when touched.
- Export APIs gated behind async jobs + human approvals.
Aftermath, signals & interview questions
- Press/legal fallout dwarfs infra cost: design reviews now demand abuse personas.
- Early signal: coefficient of variation on object-fetch latency spikes before PR crisis.
CI/CD · secrets · recurring
Build logs & artifact leaks: API keys committed once, scraped forever
Engineers accidentally publish cloud provider/developer platform/communications provider keys into CI system logs, public forks, or package artifacts: bots scan within minutes. Beginners learn APIs fail operationally when secrets double as both authentication and configuration sprinkled across repos.
Unlike interactive MFA users, API keys do not “feel” phishing, only scanners do. So prevention must be automated secret scanning + ephemeral workload credentials.
Simplified attack / failure chain
- Developer echoes env vars while debugging CI.
- Logs indexed publicly or leaked artifact tarball uploaded.
- Scanner chains temporary-credential identity probes → privilege enumeration.
- Attacker spins miners or exfiltrates buckets until cloud abuse notices.
Advanced controls & design pressure
- OIDC federation from CI → cloud roles: no long-lived cloud provider keys in CI workflows.
- Push protection + pre-commit secret scanners + nightly secret-scanning sweeps.
- Central vault injecting short-lived tokens into runtime, not plaintext env in images.
- Org-level deny policies for risky IAM actions pending tagging maturity.
Aftermath, signals & interview questions
Automated revocation outreach became common: interviews love “break-glass rotation runbook under five minutes.”
Audit deepening: OWASP API mapping
Map controls to OWASP API Security Top 10 explicitly: API1 BOLA via object-level authz tests; API5 BFLA via role-matrix tests; API7 SSRF via allowlists and blocked link-local ranges; API4 consumption via route-cost quotas; API8 misconfig via CORS/credential reviews. Scan secrets in CI, and separate gateway edge checks from service-level authorization so neither layer is assumed sufficient alone.
What must never become false
A caller who is authenticated must still fail closed when they lack object-level permission for the specific resource id in the path or body. Login ≠ ownership (OWASP API1 BOLA). Gateway auth alone does not satisfy this invariant if handlers skip the ownership check.
Failure timeline: BOLA after "we added auth"
T+0 Team ships Bearer JWT on /api/v1/orders/{id}: "auth done"
T+1d Scraper iterates id=1..5_000_000 with a valid user token
T+1d+2h Each call returns 200 for other tenants' orders (API1 BOLA)
T+2d Export job mirrors harvest; SOC sees volume, not ownership denies
T+3d Press leak; gateway rate limits would not have helped (keys were valid)
Outcome Invariant broken: authentication without object authorizationCounterexample to "JWT means secure API": valid tokens + sequential IDs + missing ownership checks equal bulk harvest.
Exercises
- Map your checkout API to OWASP API1–API7. For each risk, name one automated test and one production metric that would catch a regression.
- At 80k RPS with 900-byte audit events and 1.2 events/request, what is raw ingest MB/sec? Which OWASP risks justify keeping deny logs at 100% sample?
- A partner webhook is replayed for 90 seconds. Design HMAC + timestamp skew + idempotency so API10-style unsafe consumption and replay both fail closed.
Primary references
API security primary sources: OWASP first, then transport and OAuth hardening.
Short takeaway
Validate ruthlessly, authorize per resource (OWASP API1), throttle economically, sign critical webhooks, and instrument everything: attackers script faster than humans can grep logs. Accordions on this page stay open by default so nothing hides behind forgotten clicks.
Practice and further reading
Use these exercises to connect the lesson to a design decision. State your assumptions, trace what happens to one request, and explain the rule that must remain true even during a failure. That rule is the design's correctness invariant.
Focus for this lesson: Map API assets and trust boundaries to object/function authorization, input/output control, SSRF defenses, quotas, secrets, inventory, and tests.
Explain the decision
How do you prevent BOLA?
Read the reasoning
Authorize every object access against caller, action, tenant, and current resource state; never treat an unpredictable identifier as permission.
Apply it to a production scenario
An image-import API accepts a URL. How do you prevent SSRF?
Read one approach
Allow schemes/hosts as policy permits, resolve and validate every hop, block private/link-local metadata ranges, cap redirects/size/time, and isolate egress.
Work through the numbers
A bulk endpoint allows 500 object IDs and each check costs 2 ms serially. What naive authorization latency?
Read the worked calculation
About 1 second; batch policy/data access without weakening per-object authorization and cap request size.
Reason through a failure
What must gateway-to-service identity propagation preserve?
Read the recovery reasoning
Services trust only signed or mutually authenticated context from approved gateways and cannot accept caller-forged identity headers.
Sources and further study
Continue with Zero Trust Architecture.