Security
API Security Best Practices Every Developer Should Know
Tien Nguyen Dev.to (EN Zone)
3 views
APIs are the backbone of modern software. They power mobile apps, connect microservices, expose data to partners, and drive entire business ecosystems. And yet, APIs are also one of the most commonly exploited attack surfaces in the wild.
Whether you're a startup shipping your first REST API or a platform team managing hundreds of internal services, the fundamentals of API security don't change. What does change is how thoroughly they're applied.
Here's a breakdown of 12 best practices that should be non-negotiable on any serious API project.
1. Use Modern OAuth/OIDC + MFA
Passwords are a liability. If your API still accepts username/password credentials directly, that's a problem worth solving today.
The modern standard is OAuth 2.0 with PKCE (Proof Key for Code Exchange), combined with OpenID Connect (OIDC) for identity. PKCE prevents authorization code interception attacks - essential for public clients like mobile apps and SPAs.
On top of that, enforce Multi-Factor Authentication (MFA). Even if credentials are leaked, a second factor stops unauthorized access cold.
Issue short-lived JWT tokens (15-minute TTL is a solid default) and rely on your authorization server to handle the heavy lifting. Don't roll your own auth logic - the stakes are too high.
Key principle: Secure login with PKCE, short-lived tokens, and strong MFA.
2. Enforce Fine-Grained Authorization
Authentication asks who are you? Authorization asks what can you do? - and this is where most APIs fall short.
Broken Object Level Authorization (BOLA) is consistently ranked as the #1 API vulnerability. It happens when a user can access another user's data simply by changing an ID in the request. The classic example: user alex can access /orders/42, but can they also access /orders/99 owned by mallory? If your API doesn't check, attackers will.
Every request should pass three layers of checks before hitting the data layer:
Object Check - does this object belong to the requesting user?
Function Check - is this user allowed to call this HTTP method?
Field Check - should this user see these specific fields?
Authorization logic belongs at every layer, not just the route handler.
3. Minimize Scopes and Data
Least privilege isn't just a network security concept - it applies directly to API design.
When issuing tokens, scope them to exactly what the client needs. A mobile app that only reads user profiles doesn't need write access to billing records. When responding to requests, filter out fields the client has no business seeing. SSNs, internal IDs, salary figures, admin roles - if the client doesn't need it, strip it before it leaves the server.
Think of a scope filter as the last line of defense between your database and the outside world. The less you expose, the smaller your blast radius when something goes wrong.
4. Encrypt Every Hop
TLS is not optional. Neither is encrypting traffic between internal services.
A common misconception is that internal traffic - between your API gateway and your microservices - doesn't need encryption because it's "inside the network." That assumption fails the moment an attacker gains a foothold inside your infrastructure.
The right architecture looks like this:
External traffic: TLS 1.3 termination at the API Gateway
Internal traffic: mTLS (mutual TLS) between services, so both parties verify each other's identity
This model treats every network hop as untrusted. It's more operational overhead, but it significantly reduces the damage from a compromised internal service.
5. Protect Secrets and Keys
Hardcoded credentials in source code are a critical vulnerability. They end up in version control, get cloned by contractors, and eventually leak. The solution is centralized secret management.
Use an HSM-backed vault to store signing keys, client secrets, database credentials, and any other sensitive values. A good secrets management system provides:
Storage - secrets are never in plaintext on disk or in code
Rotation - credentials rotate automatically before they can be exploited
Revocation - compromised credentials can be invalidated instantly
Auditing - every access is logged with who, what, and when
HashiCorp Vault, AWS Secrets Manager, and GCP Secret Manager are mature options for most teams.
6. Validate Requests with Schemas
Never trust input. That's the rule. Everything coming into your API - headers, query parameters, request bodies - should be validated against a strict schema before any business logic runs.
A good schema validator will reject:
Wrong types - a string where a number is expected
Oversized payloads - a 50MB file upload to a text endpoint
Unknown fields - extra keys that shouldn't be there (they might be injection attempts)
Invalid values - internal IP addresses, malformed URLs, out-of-range numbers
Respond to malformed input with a 400 Bad Request at the pre-check stage. Don't let it reach your application layer at all.
7. Rate Limit and Cap Resources
Uncapped APIs are an invitation to abuse - whether from bots, scrapers, or a badly-written client stuck in a retry loop.
Set hard limits at the API Gateway level:
Request rate: e.g., 100 requests per minute per client
Payload size: e.g., 1 MB maximum request body
Timeout: e.g., 30 seconds before the request is dropped
Requests that exceed these limits should be blocked with a 429 Too Many Requests response. Combine rate limiting with exponential backoff guidance in your error responses, so legitimate clients degrade gracefully.
Rate limiting also protects you from the less obvious threat: a single runaway job exhausting your compute budget.
8. Defend Sensitive Business Flows
Some endpoints carry outsized risk: login, checkout, signup, OTP verification. These are high-value targets for automated abuse - credential stuffing, account enumeration, payment fraud.
Layered defenses for these flows should include:
Velocity rules - block accounts or IPs attempting more than N actions in a time window
Idempotency keys - prevent duplicate transaction submissions
CAPTCHA - challenge suspicious sessions
Step-up MFA - require a second factor for high-risk actions, even within an authenticated session
The goal is to make automated abuse economically unviable while keeping the experience smooth for real users.
9. Control Outbound and Third-Party Calls
Inbound requests aren't the only attack vector. Server-Side Request Forgery (SSRF) and malicious redirects can turn your API into a proxy for attackers.
All outbound traffic from your API should pass through an egress gate that:
Allowlists approved partner APIs and domains
Blocks redirects to unknown hosts
Rejects requests targeting internal IP ranges (like 169.254.x.x - AWS metadata endpoints)
Validates and sanitizes responses from third-party APIs before processing them
If your API fetches external URLs based on user input, this is especially critical. Never make unauthenticated requests to arbitrary destinations.
10. Harden Config and Error Handling
Default configurations are the enemy of security. Every framework, every runtime, every cloud service ships with defaults optimized for ease of use - not safety.
Harden your deployment by:
Deny by default: only explicitly allow what's needed - routes, methods, origins
Lock HTTP methods: if an endpoint only accepts GET, reject POST, PUT, and DELETE
Enforce strict CORS: whitelist specific origins, don't use * in production
Disable debug mode: stack traces and internal error details are a gift to attackers
Your error messages should be generic to external callers. Log the full detail server-side, but never expose internal paths, database errors, or stack traces in API responses.
11. Inventory APIs and Versions
You can't secure what you don't know exists. Shadow APIs - endpoints that are deployed but undocumented and unmonitored - are a persistent blind spot in large organizations.
Maintain an API registry that tracks:
Every endpoint and its current status (active, sunset, deprecated)
Every version (/v1, /v2, etc.) and its support lifecycle
Every shadow or experimental API flagged for review
Sunsetting old API versions is as important as shipping new ones. An old /v1/users endpoint still running in production, unmaintained and unpatched, is a liability. Deprecation should follow a clear timeline with client notifications.
12. Log, Detect, and Respond
Logging is not a nice-to-have - it's your incident response lifeline.
Every API should emit structured logs covering:
Authentication decisions (successes and failures)
Admin actions
Configuration changes
Anomalies and errors
What should never appear in logs: secrets, tokens, or PII (Personally Identifiable Information)
Feed these logs into a SIEM (Security Information and Event Management) system that generates real-time alerts. A spike in 401 Unauthorized responses, for example, is an early signal of a credential stuffing attack.
The goal isn't just to detect breaches - it's to detect them fast enough to respond before significant damage is done.
Putting It All Together
No single one of these practices is a silver bullet. API security is defense in depth: multiple layers, each assuming the others might fail.
Start with an honest audit of your current stack against each of these areas. Prioritize by severity: BOLA issues and unauthenticated endpoints first, operational hardening next, observability alongside everything else.
Security isn't a feature you ship once. It's a discipline you maintain continuously.
Read original: https://dev.to/tienbku/api-security-best-practices-every-developer-should-know-29gk
← Previous
Model IoT Data Before You Store It: Device, Measurement, Timestamp
Next →
Odoo CRM Implementation: 7 Practical Lessons From Real ERP Projects
Related
Comments0
No comments yet — be the first