πŸ” 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)
AspekBest PracticeJangan
AlgorithmRS256 (asymmetric)HS256 β€” secret harus dishare, gak bisa revoke per-service
ExpiryAccess: 15-60 menit. Refresh: 7-30 hariToken gak expire
StoragehttpOnly cookie (web) / memory (mobile)localStorage β€” exposed ke XSS
ClaimsMinimal: sub, iat, exp. Tambah: iss, audJangan taruh password / PII di payload
Secret rotationRotate signing key tiap 90 hariKey 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 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
FlowUse CaseSecurity Consideration
Authorization CodeWeb app with backendWajib + PKCE (Proof Key for Code Exchange)
PKCEMobile / SPAMencegah authorization code interception
Client CredentialsServer-to-serverSimple β€” client_id + client_secret
Implicit (deprecated)Legacy SPAJangan 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
CelahDeteksiFix
/api/profile?user_id=456Ganti angka β€” lihat data orangAmbil user_id dari session/token, bukan parameter
/api/invoices/INV-001EnumerationUUID instead of sequential, + owner check
Admin-only field in responseInspect response bodyJangan 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
}
LayerRate LimitContoh
GlobalPer IP1000 req/menit
Per endpointPer userLogin: 5 req/menit
Per userPer API key100 req/menit
ConcurrentMax simultan10 req/detik

Rate Limit Response

Return 429 Too Many Requests dengan header Retry-After: <seconds>. Jangan hang atau drop silent β€” client gak tahu harus nunggu berapa lama.


Input Validation β€” Defense Layer 1

AttackInput PatternDefense
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
SSRFURL ke internal IPAllowlist 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
MisconfigDampak
Access-Control-Allow-Origin: *Siapapun bisa read response via JS
Access-Control-Allow-Credentials: true + wildcardInvalid β€” browser tolak
Access-Control-Allow-Origin: nullMudah diforge via data: URI atau sandbox iframe
No Vary: OriginCache poisoning β€” proxy kirim response ke origin salah

API Key Management

PraktikKeterangan
Prefix identifikasisk_live_... vs sk_test_... β€” bedain environment
Hashed storageSimpan bcrypt hash, bukan plaintext
ScopeBatasi permission: read-only vs read-write
RotateForce rotate tiap 90 hari atau setelah bocor
RevokeEndpoint DELETE /api/v1/keys/:id


🧠 Berpikir β€” Metodologi Penyusunan Catatan

Catatan ini disusun melalui proses berpikir terstruktur sebagai berikut:

1. Thinking Type yang Digunakan

TypeKenapaBagian
Analytical ThinkingThreat model decomposition β€” memecah API attack surface jadi 3 layer (Auth, Input, Business Logic)Threat Model diagram
Systems ThinkingMemetakan interaksi CORS β†’ browser β†’ server β†’ proxy β€” bagaimana misconfig bisa cascade ke cache poisoningCORS section
Concrete ThinkingBest practice tables dengan exact β€œDo this” / β€œDon’t do that” β€” JWT config, rate limit valuesJWT, Rate Limiting, Input Validation tables
Critical ThinkingMempertanyakan asumsi umum β€” β€œJWT is secure” (HS256 gak aman untuk public API), β€œCORS * is fine untuk public API”Warnings, CORS misconfig
Design ThinkingMenentukan rate limiting strategy dari perspektif userβ€” jangan silent drop, kasih Retry-After headerRate 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

DokumenKontribusi
Web SecurityWeb application security secara umum
Cloudflare Ruleset EngineWAF layer β€” API protection at CDN level
Cyber Security RoadmapRed/Blue team perspective β€” bagaimana attacker exploit API
Network SecurityPort filtering, connection-layer security

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