π API Security β From Auth to Rate Limiting
Filosofi: API security bukan cuma βpake JWTβ. Banyak bocor di layer yg gak terduga β CORS misconfigured, rate limit gak ada, pagination tanpa auth boundary.
Threat Model β API Attack Surface
Attacker
β
ββββββββββββββββΌβββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββ ββββββββββββββ ββββββββββββββ
| Auth | | Input | | Business |
| Layer | | Layer | | Logic |
| | | | | |
| β’ JWT leak | | β’ SQLi | | β’ IDOR |
| β’ OAuth | | β’ XSS | | β’ Missing |
| redirect | | β’ SSRF | | pagination|
| β’ Token | | β’ Injection| | β’ Race |
| storage | ββββββββββββββ | condition|
ββββββββββββββ ββββββββββββββ
Authentication β Token Strategy
JWT (JSON Web Token)
Header: {"alg":"RS256","typ":"JWT"}
Payload: {"sub":"user123","iat":1680000000,"exp":1680086400}
Sign: RSA private key (RS256) atau HMAC secret (HS256)
Aspek Best Practice Jangan Algorithm RS256 (asymmetric) HS256 β secret harus dishare, gak bisa revoke per-service Expiry Access: 15-60 menit. Refresh: 7-30 hari Token gak expire Storage httpOnly cookie (web) / memory (mobile)localStorage β exposed ke XSSClaims Minimal: sub, iat, exp. Tambah: iss, aud Jangan taruh password / PII di payload Secret rotation Rotate signing key tiap 90 hari Key statis
HS256 + Public API = Risk
Kalau pake HS256, secret ada di backend dan di consumer (microservice). Satu service bocor β semua service bisa forge token. Pake RS256.
OAuth 2.0 β Authorization Framework
βββββββββββ βββββββββββ βββββββββββ
β Client ββββββββββΆβ Auth ββββββββββΆβ Resourceβ
β App β 1.auth β Server β 2.token β Server β
β βββββββββββ βββββββββββ β
βββββββββββ 3.code βββββββββββ 4.data βββββββββββ
Flow Use Case Security Consideration Authorization Code Web app with backend Wajib + PKCE (Proof Key for Code Exchange) PKCE Mobile / SPA Mencegah authorization code interception Client Credentials Server-to-server Simple β client_id + client_secret Implicit (deprecated)Legacy SPA Jangan dipakai β token di URL redirect
Authorization β Beyond Auth
IDOR (Insecure Direct Object Reference)
# β Rentan β user bisa ganti ID
GET /api/users/123/orders
# β
Ownership check required
# Backend harus verifikasi: req.user.id === order.user_id
Celah Deteksi Fix /api/profile?user_id=456Ganti angka β lihat data orang Ambil user_id dari session/token, bukan parameter /api/invoices/INV-001Enumeration UUID instead of sequential, + owner check Admin-only field in response Inspect response body Jangan kirim field yang gak di-request
Rate Limiting
// Pseudocode β sliding window
type RateLimiter struct {
Requests map [ string ][] time . Time
Max int // 100 request
Window time . Duration // per 15 menit
}
Layer Rate Limit Contoh Global Per IP 1000 req/menit Per endpoint Per user Login: 5 req/menit Per user Per API key 100 req/menit Concurrent Max simultan 10 req/detik
Return 429 Too Many Requests dengan header Retry-After: <seconds>. Jangan hang atau drop silent β client gak tahu harus nunggu berapa lama.
Attack Input Pattern Defense SQLi ' OR 1=1 --Parameterized query / ORM. JANGAN string concatenation XSS <script>alert(1)</script>Output encoding + Content-Type header NoSQLi {"$gt":""}Type validation, sanitize operator keys SSRF URL ke internal IP Allowlist domain, block private IP ranges Path traversal ../../../etc/passwdPath normalization, whitelist karakter
CORS β Sering Salah
# β Terlalu longgar
Access-Control-Allow-Origin : *
# β
Specific origin β kalau perlu
Access-Control-Allow-Origin : https://app.domain.com
Access-Control-Allow-Credentials : true
# Kalau multiple origin β parse Origin header, match allowlist
Misconfig Dampak Access-Control-Allow-Origin: *Siapapun bisa read response via JS Access-Control-Allow-Credentials: true + wildcardInvalid β browser tolakAccess-Control-Allow-Origin: nullMudah diforge via data: URI atau sandbox iframe No Vary: Origin Cache poisoning β proxy kirim response ke origin salah
API Key Management
Praktik Keterangan Prefix identifikasi sk_live_... vs sk_test_... β bedain environmentHashed storage Simpan bcrypt hash, bukan plaintext Scope Batasi permission: read-only vs read-write Rotate Force rotate tiap 90 hari atau setelah bocor Revoke Endpoint DELETE /api/v1/keys/:id
π§ Berpikir β Metodologi Penyusunan Catatan
Catatan ini disusun melalui proses berpikir terstruktur sebagai berikut:
1. Thinking Type yang Digunakan
Type Kenapa Bagian Analytical Thinking Threat model decomposition β memecah API attack surface jadi 3 layer (Auth, Input, Business Logic) Threat Model diagram Systems Thinking Memetakan interaksi CORS β browser β server β proxy β bagaimana misconfig bisa cascade ke cache poisoning CORS section Concrete Thinking Best practice tables dengan exact βDo thisβ / βDonβt do thatβ β JWT config, rate limit values JWT, Rate Limiting, Input Validation tables Critical Thinking Mempertanyakan asumsi umum β βJWT is secureβ (HS256 gak aman untuk public API), βCORS * is fine untuk public APIβ Warnings, CORS misconfig Design Thinking Menentukan rate limiting strategy dari perspektif userβ jangan silent drop, kasih Retry-After header Rate Limit Response tip
2. Background Knowledge (Pra-Penulisan)
JWT alg confusion attack : attacker ubah alg dari RS256 ke HS256, server pake public key sebagai HMAC secret β bisa forge token
OAuth implicit flow deprecated sejak RFC 9700 (2025) β semua rekomendasi pake Authorization Code + PKCE
CORS null origin : bisa diforge via data: URI, file: protocol, atau sandboxed iframe β sering lupa di-block
Rate limiting headers : X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After β standard dari RFC 6585
NoSQL injection via operators : {"$gt":""}, {"$ne":""}, {"$where": "..."} β MongoDB/LesanDB vulnerable kalau gak sanitize
IDOR dari pengalaman real : /api/profile?user_id= β lupa ambil dari token, ambil dari params = data semua user bocor
3. RAG Vault β Dokumen yang Dikonsultasi
4. Sintesis β Bagaimana Bagian Bergabung
Background Knowledge (JWT internals, OAuth flows, CORS behavior, rate limiting)
β
βΌ
RAG Vault (web security context existing)
β
βΌ
Analytical: Threat model β 3 attack surfaces β break down per layer
β
βΌ
Systems: CORS misconfig β cache poisoning chain β browser security model
β
βΌ
Critical: JWT assumptions β HS256 risk, OAuth implicit deprecated, CORS null
β
βΌ
Concrete: Best practice tables β exact config values β code samples
β
βΌ
Design: Rate limiting from user perspective β proper 429 response
5. Sequential Thinking Steps
Thought 1 (Analytical): "API security bukan cuma JWT. Ada 3 layer: Auth, Input, Business Logic."
"Buat threat model diagram biar visual."
Thought 2 (Critical): "JWT RS256 vs HS256. HS256 gak aman buat public API β secret dishare."
"Tambah alg confusion attack warning."
Thought 3 (Systems): "CORS misconfig cascade: wildcard + credentials = browser reject."
"Tapi origin di-allow semua = data bisa dibaca sitep lain."
"Cache poisoning via missing Vary: Origin."
Thought 4 (Concrete): "Rate limiting: 1000 req/menit global, 5 req/menit login. Exact values."
"Return 429 + Retry-After. Jangan silent drop."
Thought 5 (Analytical): "Input validation: 5 attack types (SQLi, XSS, NoSQLi, SSRF, Path traversal)."
"Masing-masing punya defense spesifik."
Thought 6 (Critical): "LocalStorage for tokens? No. httpOnly cookie atau memory."
Thought 7 (Design): "Bagaimana user tahu kena rate limit? Retry-After header. Jangan tebak-tebak."
π Lihat Juga