Protect your APIs from the OWASP API Top 10 and common attack patterns. Essential security practices for REST and GraphQL APIs.
APIs expose endpoints handling object IDs without proper authorization checks
Prevention: Implement proper authorization checks for every object access. Verify user ownership before returning data.
Weak authentication mechanisms allow attackers to compromise tokens or exploit implementation flaws
Prevention: Use standard auth protocols (OAuth 2.0), enforce strong passwords, implement MFA, secure token storage.
Exposing sensitive object properties or allowing mass assignment
Prevention: Define explicit allowlists for returnable/writable properties. Never expose internal properties.
No limits on API calls, file uploads, or query complexity leads to DoS
Prevention: Implement rate limiting, pagination, timeouts, and resource quotas on all endpoints.
Missing authorization checks on admin functions or sensitive operations
Prevention: Implement consistent authorization at function level. Default deny for admin endpoints.
// Storing secrets in JWT
{ "userId": 123, "apiKey": "sk_live_xxx" }
// No expiration
jwt.sign(payload, secret)
// Using alg: none
jwt.sign(payload, '', { algorithm: 'none' })// Minimal claims
{ "sub": "user_123", "exp": 1234567890 }
// Short expiration + refresh tokens
jwt.sign(payload, secret, {
algorithm: 'RS256',
expiresIn: '15m'
})// Using Zod for type-safe validation
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
age: z.number().int().min(13).max(120).optional(),
});
// In your API handler
const result = createUserSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ error: 'Invalid input' });
}Implement rate limiting to prevent abuse, brute force attacks, and DoS:
| Endpoint Type | Suggested Limit | Reason |
|---|---|---|
| Login / Auth | 5/min per IP | Prevent brute force |
| Password Reset | 3/hour per email | Prevent enumeration |
| General API | 100/min per user | Fair usage |
| Search / Heavy | 20/min per user | Resource protection |
Return 429 Too Many Requests with Retry-After header when limits are exceeded.
Use OAuth 2.0 for user-facing applications and API keys for server-to-server communication. For public APIs, consider supporting both with appropriate scoping.
Implement role-based (RBAC) or attribute-based (ABAC) access control. Check permissions at both route and object level. Never rely solely on frontend hiding features.
Neither is inherently more secure. GraphQL has unique concerns (query depth, batching attacks) while REST has its own (IDOR, verb tampering). Both require proper authentication, authorization, and input validation.
Use URL or header versioning. When patching security issues, backport to all supported versions. Have a clear deprecation policy that encourages upgrades.
Find authentication bypasses, authorization issues, and input validation problems in your API.
Scan Your API FreeLast updated: January 2025