Modern applications are API-first: microservices, mobile apps, and third-party integrations all rely on APIs. But authentication alone isn't enough—comprehensive API security requires defense-in-depth across authorization, input validation, rate limiting, and threat detection.
The OWASP API Security Top 10 (2023)
Understanding the most critical API risks is the foundation of effective API security.
Top API Vulnerabilities:
- Broken Object Level Authorization (BOLA): User A can access User B's data by changing object IDs
- Broken Authentication: Weak token validation, credential stuffing, missing MFA
- Broken Object Property Level Authorization: Exposing sensitive fields or allowing mass assignment
- Unrestricted Resource Consumption: No rate limiting, allowing DoS attacks
- Broken Function Level Authorization: Regular users accessing admin endpoints
- Unrestricted Access to Sensitive Business Flows: Automated abuse (e.g., scalping, inventory hoarding)
- Server Side Request Forgery (SSRF): API makes requests to internal resources
- Security Misconfiguration: Verbose error messages, CORS issues, outdated software
- Improper Inventory Management: Undocumented or shadow APIs
- Unsafe Consumption of APIs: Trusting third-party API data without validation
1. Authentication & Authorization
Use OAuth 2.0 / OpenID Connect
OAuth 2.0 is the industry standard for API authorization. Use authorization code flow with PKCE for maximum security.
OAuth 2.0 Best Practices:
- Short-lived Access Tokens: 15-60 minutes expiry, refresh with long-lived refresh tokens
- Use PKCE: Proof Key for Code Exchange prevents authorization code interception
- Validate Tokens Properly: Verify signature, expiration, issuer, audience claims
- Scope-Based Access: Grant minimum necessary permissions via OAuth scopes
Implement Proper Authorization
Authentication (who you are) ≠ Authorization (what you can do). Always verify permissions before processing requests.
Example: Preventing BOLA (Insecure Direct Object Reference)
// ❌ VULNERABLE: No authorization check
app.get('/api/users/:userId/orders/:orderId', (req, res) => {
const order = db.getOrder(req.params.orderId);
res.json(order); // Anyone can access any order!
});
// ✅ SECURE: Verify ownership before returning data
app.get('/api/users/:userId/orders/:orderId', authenticate, (req, res) => {
const order = db.getOrder(req.params.orderId);
// Authorization check: Does this order belong to the authenticated user?
if (order.userId !== req.user.id) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(order);
});2. Input Validation & Output Encoding
Validate All Inputs
Never trust user input. Validate data type, format, length, and business logic constraints.
Example: Schema Validation (Joi/Zod)
import { z } from 'zod';
// Define request schema
const CreateUserSchema = z.object({
email: z.string().email().max(255),
password: z.string().min(12).max(128),
age: z.number().int().min(18).max(120),
role: z.enum(['user', 'admin']).default('user')
});
app.post('/api/users', (req, res) => {
// Validate request body
const result = CreateUserSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: 'Validation failed',
details: result.error.issues
});
}
// Proceed with validated data
const user = createUser(result.data);
res.status(201).json(user);
});Prevent Mass Assignment
Don't blindly accept all properties from request body—attackers can modify sensitive fields.
Mass Assignment Example
// ❌ VULNERABLE
app.put('/api/users/:id', (req, res) => {
User.update(req.params.id, req.body); // Attacker can set role: 'admin'!
});
// ✅ SECURE: Explicitly allow only specific fields
app.put('/api/users/:id', (req, res) => {
const allowedFields = ['name', 'email', 'bio'];
const updates = _.pick(req.body, allowedFields);
User.update(req.params.id, updates);
});3. Rate Limiting & DoS Protection
Implement Tiered Rate Limiting
Different endpoints have different abuse risks. Apply appropriate limits:
Recommended Rate Limits:
- Authentication endpoints: 5 requests/15 minutes (prevent brute-force)
- Password reset: 3 requests/hour per email
- Read operations: 100 requests/minute per user
- Write operations: 30 requests/minute per user
- Global API: 10,000 requests/hour per API key
Example: Express Rate Limiter
import rateLimit from 'express-rate-limit';
// Global rate limiter
const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
standardHeaders: true,
legacyHeaders: false,
});
// Strict limiter for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
skipSuccessfulRequests: true, // only count failed attempts
});
app.use('/api/', globalLimiter);
app.use('/api/auth/', authLimiter);4. API Security Headers
Configure security headers to protect against common attacks:
Essential Headers:
// Content Security Policy Content-Security-Policy: default-src 'self' // Prevent MIME type sniffing X-Content-Type-Options: nosniff // Clickjacking protection X-Frame-Options: DENY // XSS protection (legacy browsers) X-XSS-Protection: 1; mode=block // Force HTTPS Strict-Transport-Security: max-age=31536000; includeSubDomains // CORS configuration Access-Control-Allow-Origin: https://trusted-domain.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Authorization, Content-Type Access-Control-Allow-Credentials: true
5. API Logging & Monitoring
What to Log
- ✓ Authentication events: Login attempts (success/failure), password resets
- ✓ Authorization failures: 403 Forbidden responses (BOLA attempts)
- ✓ Rate limit hits: Identify abusive clients
- ✓ Input validation errors: Detect attack patterns (SQLi, XSS attempts)
- ✓ Anomalous behavior: Unusual request volumes, geographic anomalies
- ❌ DO NOT LOG: Passwords, API keys, credit card numbers, PII
Threat Detection Patterns
Use SIEM rules to detect API attacks:
- Credential Stuffing: > 10 failed logins from same IP in 5 minutes
- BOLA Enumeration: Sequential object ID access with mix of 200/403 responses
- Scraping: High volume of GET requests to catalog/product endpoints
- API Key Abuse: Single API key used from multiple IPs/geolocations
6. API Versioning & Deprecation
Maintain security across API versions:
Best Practices:
- Version in URL: /api/v1/users, /api/v2/users (clear and explicit)
- Security Backports: Apply critical security patches to all supported versions
- Deprecation Policy: Announce 6 months in advance, return warnings in response headers
- Sunset Header:
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
7. API Security Testing
Comprehensive Testing Strategy
1. Automated Security Scanning
Tools: OWASP ZAP, Burp Suite, StackHawk, Postman Security Tests
2. Fuzzing
Send malformed inputs, oversized payloads, special characters to test error handling
3. Business Logic Testing
Manual testing of authorization flows, payment processing, multi-step transactions
4. Load Testing
Validate rate limiting, circuit breakers, graceful degradation under load
5. Penetration Testing
Annual engagements by external security firms
API Security Checklist
- Authentication: OAuth 2.0 with PKCE, short-lived tokens, MFA for privileged operations
- Authorization: Verify ownership on every object access, implement RBAC/ABAC
- Input Validation: Schema validation (Zod/Joi), sanitize SQL/NoSQL queries, prevent mass assignment
- Rate Limiting: Tiered limits per endpoint, IP-based + user-based, monitoring for abuse
- Security Headers: CSP, HSTS, X-Frame-Options, proper CORS configuration
- Encryption: TLS 1.3+ for transport, sensitive fields encrypted at rest
- Logging: Auth events, authorization failures, rate limit hits (no PII/secrets)
- Testing: DAST scans in CI/CD, annual pentests, business logic testing
- API Inventory: Documented APIs, no shadow endpoints, version deprecation policy
Protect Your APIs with Securus Mind
Automated API discovery, vulnerability scanning, and real-time threat detection for modern API-first applications.