👤 Consumer: Identitas di Kong
consumers:
- username: mitra-a
custom_id: "PARTNER-001"
tags: ["mitra", "tier-premium"]
keyauth_credentials:
- key: "${MITRA_A_KEY}"
acls:
- group: premium
- username: aplikasi-mobile
jwt_secrets:
- key: "aplikasi-mobile"
algorithm: RS256
rsa_public_key: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
Setelah autentikasi berhasil, Kong meneruskan identitas ke upstream lewat header:
X-Consumer-ID: 4f1a...
X-Consumer-Username: mitra-a
X-Consumer-Custom-ID: PARTNER-001
X-Credential-Identifier: ...
🔑 Memilih Metode
| Metode | Tepat untuk | Catatan |
|---|---|---|
key-auth | Integrasi server-ke-server, API mitra | Sederhana; kunci harus dirotasi berkala |
jwt | Aplikasi web & mobile | Tanpa state; Kong memverifikasi tanda tangan |
oauth2 | Akses pihak ketiga atas nama pengguna | Paling rumit; Kong menjadi authorization server |
basic-auth | Alat internal saja | Kredensial dikirim tiap permintaan — wajib HTTPS |
openid-connect | Integrasi dengan Keycloak, Auth0, dll | Fitur enterprise |
plugins:
- name: key-auth
service: layanan-mitra
config:
key_names: ["apikey", "x-api-key"]
key_in_header: true
key_in_query: false # JANGAN izinkan kunci di query string
key_in_body: false
hide_credentials: true # jangan teruskan kunci ke upstream
URL lengkap tercatat di log akses proxy, log server, riwayat peramban, header Referer, dan sistem pemantauan. Kunci yang dikirim lewat query string akan tersebar ke tempat-tempat yang tidak Anda kendalikan dan bertahan lama di sana. Selalu setel key_in_query: false dan wajibkan kunci dikirim lewat header.
🎫 JWT
plugins:
- name: jwt
service: layanan-pesanan
config:
claims_to_verify: ["exp", "nbf"]
key_claim_name: iss
secret_is_base64: false
run_on_preflight: false # biarkan preflight CORS lewat
claims_to_verify tidak memeriksa kedaluwarsa secara bawaan
Bila exp tidak dicantumkan dalam claims_to_verify, Kong akan menerima token yang tanda tangannya sah meski sudah kedaluwarsa bertahun-tahun. Ini kesalahan konfigurasi yang mudah terlewat karena semuanya tampak bekerja normal. Selalu sertakan exp.
🕵️ Anonymous Consumer
plugins:
- name: key-auth
config:
anonymous: "${ID_CONSUMER_ANONIM}" # ← perhatikan baik-baik
Dengan anonymous disetel, permintaan tanpa kredensial tetap diloloskan dan diperlakukan sebagai consumer anonim. Niat aslinya adalah mendukung akses berjenjang — anonim dapat kuota kecil, terautentikasi dapat kuota besar. Tetapi bila Anda mengiranya sebagai autentikasi wajib, Anda baru saja membuka API Anda ke publik.
Bila memakainya, wajib pasangkan dengan plugin acl yang menolak grup anonim pada endpoint sensitif. Bila tidak butuh akses berjenjang, jangan setel sama sekali.
🛡️ ACL: Otorisasi Setelah Autentikasi
plugins:
- name: acl
route: rute-admin
config:
allow: ["admin", "internal"]
hide_groups_header: true
- name: acl
route: rute-premium
config:
deny: ["anonymous", "trial"]
Autentikasi menjawab "siapa Anda"; ACL menjawab "apakah Anda boleh". Keduanya berpasangan — plugin auth menetapkan consumer, lalu ACL memeriksa keanggotaan grupnya.
🔒 Gateway Bukan Satu-satunya Penjaga
Layanan Anda menerima X-Consumer-Username dari Kong dan mungkin memakainya untuk otorisasi. Masalahnya: bila seseorang bisa menjangkau layanan Anda langsung tanpa melewati gateway, ia bisa mengirim header itu dengan nilai apa pun dan menyamar sebagai siapa saja.
Pertahanannya berlapis: (1) layanan hanya boleh menerima koneksi dari gateway — lewat NetworkPolicy, security group, atau mTLS; (2) untuk sistem yang sensitif, layanan memverifikasi sendiri token aslinya alih-alih memercayai header; (3) jangan pernah menganggap "ada di belakang gateway" sama dengan "aman".