How do you secure API endpoints?
API security: three families of mistakes, not a top ten list
Real breaches come from missing checks, leaked fields and trusted input.
For this question · chapters 1 and 3 of 3
The route nobody gated
- Real breaches rarely come from weak cryptography, but usually from a missed check. This request carries a token for the user role, and TLS protects the request on the wire. The request is validated against a few checks : authentication and the route role first. The object owner and the field scope come next, and these checks combined secure the endpoint.
- TLS protects the request while it travels. The request passes all four checks and server responds with a 200. A breach is usually a missed check on the request.
- Authentication only says who the caller is. All three routes pass that check. But GET /admin/users needs a role check too, and it is missing.
- The same token carries the user role, but the admin route never checks it. The server returns 200 with 1,204 email addresses, no exploit needed. OWASP calls this broken function level authorization, API5.
- The endpoint GET /users/124/orders checks authentication and role, but not ownership. The role check passes any normal user, so any other user can read user 124's orders. That missing check is broken object level authorization, OWASP API1.
- A default-deny policy fixes the function level gap. Every route stays closed unless it is listed as open. So a route nobody remembered is a route nobody can reach.
Guardrails are the third family
- Nothing limits one client's traffic, so the rate hits 2400 req/s and p99 latency reaches 9.8 seconds. Unrestricted resource consumption, OWASP-API4, is a cost and an outage before it is ever a hack.
- A rate limiter rejects anything above 1000 requests a second and returns 429. The limit is about capacity and fairness between callers.
- The service parses the whole request body before any handler runs. A 10 MB string and a nested array reach the parser first, so the parser can be attacked too. A schema closes that gap, so the service rejects the next oversized body with a 400. Check shape, size and type on the way in, every field, every time.
- A normal user calls GET /admin/users and the server answers 200. The service log records nothing, so nobody will ever know about that call. Log every request: the time, the user, the method, the path and the status. Logging turns a breach into an incident you can investigate, so log who called what. But don't log the secrets the caller sent.
- A scanner sends requests to the service. The path /beta answers 404, /v2 answers 200, and the deprecated /v1 still answers 200. Nobody documented /v1 for two years, and the service never stopped running it. Improper inventory, OWASP-API9: hiding an endpoint does not secure it, and forgetting an endpoint does not remove it.
- A Sunset header on the /v1 route indicates the route's last day, 31 Dec 2026. Retiring means ending a version without breaking the clients that still use that version.
Real breaches rarely come from weak cryptography, but usually from a missed check. This request carries a token for the user role, and TLS protects the request on the wire. The request is validated against a few checks : authentication and the route role first. The object owner and the field scope come next, and these checks combined secure the endpoint.
Three families cover the OWASP top ten. Access control - a check on every route and a check on every object. Trust - a declared shape for every response and every request. Guardrails - a limit, a schema, and a log, plus a sunset date for every old version.
© LearnThatStack - diagrams may not be republished without permission.
Want a quick review of the fundamentals? See the API Design cheatsheet.
74 of 92 API Design answers are in Pro.
Full answers, code samples, and AI explanations that go simpler or deeper. Cancel anytime.
- Full answers + code
- AI explanations, simpler or deeper
- 1,000 AI credits / month
- Cancel anytime