API security checklist 20 điểm tổng hợp từ OWASP API Top 10 + kinh nghiệm production. Mỗi điểm có mức độ critical/high/medium — anh ưu tiên fix theo thứ tự.
Authentication & Authorization (5)
- ✅ 1. Mọi endpoint require auth (trừ /healthz, /login, /signup). Default deny.
- ✅ 2. Verify ownership mọi resource — check user_id match. BOLA là vuln #1.
- ✅ 3. Role-based access — admin vs user check explicit, không tin token claim.
- ✅ 4. Token TTL ngắn — access < 15 phút, refresh rotation. Xem JWT.
- ✅ 5. MFA cho action critical — change password, withdraw funds, change email.
// Pattern verify ownership
app.get('/orders/:id', requireAuth, async (req, res) => {
const order = await db.orders.findById(req.params.id)
if (!order) return res.status(404).end()
if (order.user_id !== req.user.id && req.user.role !== 'admin') {
return res.status(403).end()
}
res.json(order)
})
Input Validation (4)
- ✅ 6. Schema validation mọi body/query — Zod, Joi, Yup.
- ✅ 7. Whitelist field — strict mode reject extra field (mass assignment).
- ✅ 8. Type coercion — string → int safely, validate range.
- ✅ 9. Length limit — string max 1MB, array max 1000 item.
import { z } from 'zod'
const updateUserSchema = z.object({
name: z.string().min(1).max(100),
bio: z.string().max(500).optional(),
}).strict() // ← reject extra field như { role: 'admin' }
app.patch('/users/:id', requireAuth, async (req, res) => {
const result = updateUserSchema.safeParse(req.body)
if (!result.success) return res.status(400).json({ errors: result.error.flatten() })
await db.users.update(req.params.id, result.data)
res.status(204).end()
})
Rate Limiting (3)
- ✅ 10. Per-user rate limit — chống abuse từ account.
- ✅ 11. Per-IP rate limit — chống bot, brute-force.
- ✅ 12. Per-endpoint expensive — /generate-report, /export 10 req/giờ thay vì 100.
Detail trong Rate limiting.
Data Exposure (3)
- ✅ 13. Response schema tách khỏi DB — không trả password_hash, internal_notes.
- ✅ 14. Pagination — không trả 100k record. Cursor-based cho large dataset.
- ✅ 15. Error message không leak — "Login failed" không phải "Email not found" (enum email).
// ❌ Trả full user object
app.get('/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id)
res.json(user) // → có password_hash, two_factor_secret, etc.
})
// ✓ Pick field cần
app.get('/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id)
res.json({
id: user.id, name: user.name, avatar: user.avatar,
// KHÔNG: email, password_hash, internal_*, etc.
})
})
Transport & Headers (3)
- ✅ 16. HTTPS only + HSTS — TLS 1.3, max-age 1 năm.
- ✅ 17. CORS whitelist — không "*" cho API có credentials.
- ✅ 18. Security headers — helmet middleware (15+ header).
Logging & Monitoring (2)
- ✅ 19. Log security event — failed login, 403 access, rate limit hit. Ship vào SIEM.
- ✅ 20. Alert anomaly — spike 401/403, unusual user activity. PagerDuty/Slack.
Bonus điểm
- API key cho machine-to-machine — rotate 90 ngày
- Webhook signature HMAC — xem Webhook design
- Idempotency key cho payment — xem Idempotency
- Versioning từ ngày 1 — /v1/ prefix
- OpenAPI spec với security schema
- Pen test định kỳ 6-12 tháng
Kết luận
API security checklist 20 điểm cover ~95% threat. Áp dụng từ ngày 1 — retrofit tốn gấp 5 lần. Tools tự động (ESLint security, ZAP, Snyk) catch lỗi sớm, nhưng pen test thật bởi 3rd party là validation cuối. Đọc OWASP Top 10 để hiểu vector attack rộng hơn.