Securing APIs requires a multi-layered approach beyond just JWT tokens. We’ll cover rate limiting, input sanitization, OWASP top 10 for APIs, and security headers.
Markup Showcase: API Security
Headings and narrative
Security relies on layered controls: authentication, authorization, validation, monitoring, and response. Defense‑in‑depth reduces the blast radius when a single control fails.
Emphasis and links
Always validate inputs at trust boundaries. See the
OWASP API Security Top 10 and internal
security checklist for rollout steps. Avoid leaking sensitive data; mask values like Authorization: Bearer *** in logs.
Lists
- Authentication: short‑lived tokens, refresh flows, clock skew handling
- Authorization: least privilege, ABAC/RBAC, deny by default
- Validation: schema‑based (e.g.,
zod,ajv) at the edge and service- Normalize encodings
- Enforce size limits
- Reject unknown fields
- Add rate limiter per IP + token
- Enable anomaly detection on GraphQL operations
Caution: Security headers such as
Content-Security-PolicyandStrict-Transport-Securityshould be applied consistently across all routes.
Inline code
Return minimal error messages like 400 Bad Request with a machine‑readable body, but never echo untrusted input in the message.
Code blocks (TypeScript)
import { z } from "zod";
const Payload = z.object({
email: z.string().email(),
plan: z.enum(["free", "pro", "enterprise"]).default("free"),
});
export async function handler(req: Request) {
const ip = req.headers.get("x-forwarded-for") ?? "unknown";
// Simple rate limit interface (pseudo)
const allowed = await rateLimit.allow({
key: `signup:${ip}`,
limit: 20,
window: 60_000,
});
if (!allowed) return new Response("Too Many Requests", { status: 429 });
const json = await req.json();
const parsed = Payload.safeParse(json);
if (!parsed.success) {
return new Response(JSON.stringify({ error: "invalid_payload" }), {
status: 400,
headers: { "content-type": "application/json" },
});
}
// ... business logic
return new Response(JSON.stringify({ ok: true }), { status: 200 });
}
JSON example
{
"security": {
"rateLimit": { "windowMs": 60000, "max": 100 },
"cors": { "origins": ["https://example.com"], "allowCredentials": false },
"headers": [
"Strict-Transport-Security: max-age=31536000; includeSubDomains",
"X-Content-Type-Options: nosniff"
]
}
}
HTML snippet
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src https: data:; object-src 'none'"
/>
Table
| Control | Purpose | Example |
|---|---|---|
| Rate limiting | Throttle abuse | token+IP sliding window |
| Input validation | Prevent injection | JSON schema at gateway |
| Content Security | Reduce XSS vectors | CSP with nonces |