API Security
API
Authentication
Authorization
Design Patterns
+1 more

Secure API Design Patterns: A Developer's Guide

SCR Team
November 28, 2025
14 min read
Share

Why API Security Should Be Your Top Priority

APIs now account for over 83% of all web traffic (Cloudflare, 2024). They power mobile apps, microservices, third-party integrations, and increasingly, AI-driven workflows. But this also makes them the #1 attack vector for data breaches.

The numbers tell the story:

MetricValue
API attacks increased (YoY)681% (Salt Security)
Breaches involving APIs1 in 3 enterprise incidents
Average cost of an API breach$6.1 million
APIs with auth vulnerabilities61% of tested APIs

Reality check: If your API lacks proper security controls, it's not a matter of if you'll be breached — it's when.


Authentication: Getting the Front Door Right

Authentication verifies who is making the request. Get it wrong, and every other security measure becomes irrelevant.

JWT (JSON Web Token) Best Practices

JWTs are the most common API authentication mechanism, but they're frequently misimplemented. Follow these rules:

  • Keep access tokens short-lived — 15 minutes maximum. Shorter tokens limit the damage window if one is stolen.
  • Implement refresh token rotation — Issue a new refresh token with every use and invalidate the old one.
  • Store tokens in httpOnly cookies — Never in localStorage or sessionStorage, which are vulnerable to XSS.
  • Validate every claim — Check iss, aud, exp, and iat on every request. Don't just verify the signature.
  • Use asymmetric signing — RS256 or ES256 is preferred over HS256 in distributed systems.

API Key Security

API keys are not authentication — they're identification. But if you use them:

  • Never expose keys in client-side code — They belong in server environments only
  • Rotate keys on a regular schedule — Quarterly at minimum, immediately after any suspected compromise
  • Use separate keys per environment — Development, staging, and production should never share keys
  • Scope keys to specific actions — Read-only keys shouldn't allow writes

OAuth 2.0 + PKCE

For user-facing applications, OAuth 2.0 with PKCE (Proof Key for Code Exchange) is the gold standard:

  • Eliminates the need for client secrets in public clients
  • Prevents authorization code interception attacks
  • Supported by all major identity providers (Auth0, Okta, Azure AD)

Authorization: Controlling Who Sees What

Authentication tells you who someone is. Authorization controls what they can do.

RBAC — Role-Based Access Control

The simplest model. Assign roles to users, and roles map to permissions.

Best for: Applications with well-defined user roles (admin, editor, viewer).

Common roles and their scope:

RoleCreateReadUpdateDelete
AdminYesYesYesYes
EditorYesYesYesNo
ViewerNoYesNoNo
API ConsumerNoYesNoNo

ABAC — Attribute-Based Access Control

More granular than RBAC. Decisions are based on user attributes, resource attributes, and environmental conditions.

Best for: Complex organizations where access depends on department, location, time of day, or data classification.

Example decision factors:

  • User's department and clearance level
  • Resource's sensitivity classification (public, internal, confidential)
  • Request origin (corporate VPN vs. public internet)
  • Time of day (business hours vs. off-hours)

Authorization Anti-Patterns to Avoid

  • Client-side only checks — Always enforce on the server. Frontend checks are UX, not security.
  • Hardcoding roles in code — Use a policy engine (OPA, Casbin) for maintainability.
  • Missing object-level checks — Verify the user owns or has access to the specific resource, not just the resource type.

Rate Limiting: Slowing Down Attackers

Without rate limiting, your API is an open buffet for brute-force attacks, credential stuffing, and denial of service.

Multi-Tier Rate Limiting Strategy

Implement limits at multiple levels for defense in depth:

  • Per-user limits — 100 requests/minute for authenticated users
  • Per-IP limits — 30 requests/minute for unauthenticated traffic
  • Per-endpoint limits — Stricter limits on sensitive endpoints (login, password reset)
  • Global limits — Circuit breakers to prevent infrastructure overload

Rate Limit Response Headers

Always include these headers so clients can self-regulate:

  • X-RateLimit-Limit — Maximum requests allowed
  • X-RateLimit-Remaining — Requests remaining in the window
  • X-RateLimit-Reset — Unix timestamp when the limit resets
  • Retry-After — Seconds to wait before retrying (on 429 response)

Input Validation: Trust Nothing

Every piece of data crossing your API boundary is potentially malicious. Validate everything.

Validation Principles

  • Validate on the server — Client-side validation is a UX feature, not a security control
  • Use allowlists over blocklists — Define what's accepted, not what's rejected
  • Enforce strict types — An age field should only accept integers, not strings
  • Limit payload sizes — Set maximum body sizes to prevent memory exhaustion
  • Sanitize before storage — Strip HTML tags, escape special characters

Schema Validation

Use schema validation libraries to enforce structure:

  • Zod (TypeScript) — Compile-time type inference + runtime validation
  • Joi (Node.js) — Mature, well-documented, extensive validation rules
  • JSON Schema — Language-agnostic, widely supported

Security Headers Every API Needs

HeaderValuePurpose
Strict-Transport-Securitymax-age=31536000; includeSubDomainsForce HTTPS
Content-Security-Policydefault-src 'none'Prevent content injection
X-Content-Type-OptionsnosniffPrevent MIME sniffing
X-Frame-OptionsDENYPrevent clickjacking
Cache-Controlno-storePrevent sensitive data caching
X-Request-ID(unique per request)Enable request tracing

API Security Checklist

Before going live, verify every item:

  • Authentication — All endpoints require valid credentials (except public ones explicitly marked)
  • Authorization — Object-level and function-level access controls enforced
  • Input validation — Schema validation on all request bodies, query params, and headers
  • Rate limiting — Configured per-user, per-IP, and per-endpoint
  • HTTPS only — TLS 1.2+ enforced, HTTP redirected or blocked
  • Error handling — Generic error messages to clients, detailed logs server-side
  • Logging — All authentication events, authorization failures, and anomalies logged
  • Versioning — API versioned to allow secure deprecation of old endpoints
  • CORS — Configured with specific origins, not wildcard (*)
  • Dependencies — All libraries scanned for known vulnerabilities

Final thought: Security isn't a feature you bolt on at the end. It's a design constraint you build around from the first line of code.

Advertisement