REST API Security Reference

rest api security


Security Design Principles

Based on Saltzer and Schroeder’s foundational paper The Protection of Information in Computer Systems.

Least Privilege

An entity should only have the minimum required permissions to perform authorized actions. Permissions should be granted as needed and revoked when no longer in use.

Fail-Safe Defaults

A user’s default access to any system resource should be denied unless explicitly granted.

Economy of Mechanism

Design should be as simple as possible. Component interfaces and interactions should be easy to understand.

Complete Mediation

Access rights to resources should always be validated. Systems should not rely on cached permission matrices, as outdated permissions can lead to security violations.

Open Design

Security should not rely on secrecy. The system should be designed transparently without hidden algorithms.

Separation of Privilege

Access should not be granted based on a single condition. Instead, multiple conditions should be evaluated based on the resource type.

Least Common Mechanism

Shared state among components should be minimized to prevent corruption from affecting multiple parts of the system.

Psychological Acceptability

Security mechanisms should not interfere with usability. If security makes the system too difficult to use, users may find ways to bypass it.


REST API Security Checklist

Always Use HTTPS

Using SSL/TLS ensures encrypted communication and simplifies authentication using randomly generated access tokens. If HTTP/2 is used, multiple requests can be sent over a single connection, reducing TCP and SSL handshake overhead.

Use Password Hashing

Passwords should always be hashed using secure algorithms such as PBKDF2, bcrypt, or scrypt to mitigate damage in case of a data breach.

Never Expose Sensitive Data in URLs

Usernames, passwords, session tokens, and API keys should never appear in URLs, as they can be logged by web servers and exposed.

Bad:

https://api.example.com/users?apiKey=abcd123456789

Good:

Authorization: Bearer abcd123456789

Input Parameter Validation

Validate request parameters at the very first step before they reach application logic. Implement strong validation checks and reject invalid requests immediately.

Add Request Timestamps

Including a timestamp in API requests as a custom HTTP header can help prevent replay attacks. The server should reject requests with timestamps older than a defined threshold (e.g., 30 seconds).


OAuth 2.0

OAuth 2.0 allows third-party applications to obtain limited access to HTTP services without sharing credentials.

Key Concepts

TermDescription
Resource OwnerUser who owns the data
ClientApplication requesting access
Authorization ServerIssues tokens after authentication
Resource ServerAPI that holds protected resources
Access TokenShort-lived token for API access
Refresh TokenLong-lived token to get new access tokens

Common Flows

FlowUse Case
Authorization CodeServer-side web apps (most secure)
Authorization Code + PKCEMobile/SPA apps (recommended)
Client CredentialsMachine-to-machine (no user)
ImplicitLegacy SPAs (deprecated, use PKCE)

Authorization Code Flow

1. App redirects user to Auth Server
   GET /authorize?response_type=code&client_id=xxx&redirect_uri=xxx&scope=read

2. User authenticates and consents

3. Auth Server redirects back with code
   GET /callback?code=AUTH_CODE

4. App exchanges code for tokens (server-side)
   POST /token
   grant_type=authorization_code&code=AUTH_CODE&client_id=xxx&client_secret=xxx

5. Auth Server returns access_token and refresh_token

Token Refresh

POST /token
Content-Type: application/x-www-form-urlencoded
 
grant_type=refresh_token&refresh_token=REFRESH_TOKEN&client_id=xxx

JWT (JSON Web Tokens)

Compact, URL-safe tokens for transmitting claims between parties.

Structure

header.payload.signature

Header:

{"alg": "HS256", "typ": "JWT"}

Payload (Claims):

{
  "sub": "user123",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622,
  "roles": ["admin"]
}

Signature:

HMACSHA256(base64(header) + "." + base64(payload), secret)

Common Claims

ClaimDescription
subSubject (user ID)
iatIssued at (timestamp)
expExpiration (timestamp)
issIssuer
audAudience

Best Practices

  • Use short expiration times (15 min - 1 hour)
  • Store in memory or httpOnly cookies (not localStorage)
  • Validate signature on every request
  • Check exp and iss claims
  • Use RS256 (asymmetric) for distributed systems

Rate Limiting

Protect APIs from abuse and ensure fair usage.

Common Strategies

StrategyDescription
Fixed WindowN requests per time window (e.g., 100/minute)
Sliding WindowRolling window for smoother limits
Token BucketTokens refill over time, requests consume tokens
Leaky BucketRequests queued and processed at fixed rate

Response Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1609459200

Rate Limit Exceeded

HTTP/1.1 429 Too Many Requests
Retry-After: 60

Implementation Considerations

  • Rate limit by API key, user, or IP
  • Different limits for different endpoints
  • Higher limits for authenticated users
  • Gradual backoff for repeat offenders

API Security Headers

# Prevent MIME sniffing
X-Content-Type-Options: nosniff
 
# Prevent clickjacking
X-Frame-Options: DENY
 
# Enable browser XSS filter
X-XSS-Protection: 1; mode=block
 
# Control referrer information
Referrer-Policy: strict-origin-when-cross-origin
 
# Content Security Policy
Content-Security-Policy: default-src 'self'
 
# Strict Transport Security
Strict-Transport-Security: max-age=31536000; includeSubDomains

Common Vulnerabilities

VulnerabilityMitigation
Injection (SQL, NoSQL)Parameterized queries, input validation
Broken AuthenticationMFA, secure token storage, rate limiting
Excessive Data ExposureReturn only needed fields, filter sensitive data
Broken Access ControlValidate permissions on every request
Mass AssignmentWhitelist allowed fields
SSRFValidate and sanitize URLs, block internal IPs
CORS MisconfigurationWhitelist specific origins, avoid *