Sebagian besar bug JWT di TypeScript tidak ada pada token-nya — melainkan pada konfigurasi verifikasinya. Batasan algoritma yang hilang, claim penerbit yang tak diperiksa, atau secret berumur pendek bisa diam-diam merusak autentikasi sedemikian rupa hingga hanya muncul di produksi. Panduan ini menelusuri setiap dimensi ketepatan konfigurasi JWT di TypeScript: algoritma, validasi claim, kebersihan secret, penanganan kedaluwarsa, serta alat berbasis browser yang mempercepat debugging.
Apa yang dicakup validasi konfigurasi JWT
JSON Web Token (JWT) adalah string ringkas yang aman untuk URL, terdiri dari tiga bagian berenkode Base64URL yang dipisah titik: header yang menyatakan algoritma dan jenis token, payload yang membawa claim, dan tanda tangan yang mengikat keduanya. Memvalidasi JWT berarti memastikan ketiga bagian utuh dan claim-nya memenuhi persyaratan aplikasi Anda — bukan sekadar tanda tangannya benar secara matematis.
Dua lapis validasi JWT
Validasi kriptografis mengonfirmasi tanda tangan: server memastikan token ditandatangani dengan kunci yang diharapkan dan tidak dimanipulasi. Validasi konfigurasi melangkah lebih jauh: ia memeriksa bahwa token diterbitkan oleh otoritas yang tepat, ditujukan untuk layanan spesifik ini, belum kedaluwarsa, dan membawa claim kustom yang diharapkan. Sebagian besar kerentanan keamanan JWT berasal dari validasi konfigurasi yang tidak lengkap, bukan dari kriptografi yang rusak.
- Algoritma (`alg`) - harus sama persis dengan konfigurasi server Anda; jangan pernah menebaknya dari header token
- Kedaluwarsa (`exp`) - token tidak boleh melewati stempel waktu kedaluwarsanya, dengan memperhitungkan toleransi jam
- Tidak-sebelum (`nbf`) - token tidak boleh dipakai sebelum waktu valid paling awalnya
- Penerbit (`iss`) - token harus berasal dari layanan autentikasi tepercaya Anda
- Audiens (`aud`) - token harus ditujukan untuk API atau layanan spesifik ini
- Claim kustom - peran, scope, ID tenant, atau field spesifik aplikasi mana pun yang jadi tumpuan logika Anda
Note
Pemeriksaan algoritma dan konfigurasi kunci
Konfigurasi algoritma adalah pengaturan paling kritis dari sisi keamanan dalam verifikasi JWT. Salah menatanya membuka kelas serangan yang melewati autentikasi sepenuhnya. Pustaka JWT TypeScript menyediakan alat untuk menegakkannya dengan benar - tetapi hanya jika Anda memakainya secara eksplisit.
HS256 vs RS256 - memilih algoritma yang tepat
| Properti | HS256 (simetris) | RS256 (asimetris) |
|---|---|---|
| Jenis kunci | Secret bersama (kunci sama untuk menandatangani + memverifikasi) | Pasangan kunci RSA (privat untuk menandatangani, publik untuk memverifikasi) |
| Distribusi kunci | Setiap verifikator memegang secret | Hanya penerbit yang memegang kunci privat |
| Keamanan multi-layanan | ✗ Berisiko - semua verifikator dapat memalsukan token | ✓ Verifikator hanya memegang kunci publik |
| Dukungan OIDC / JWKS | ✗ Tidak berlaku | ✓ Kunci publik disajikan lewat endpoint JWKS |
| Performa | ✓ Cepat (HMAC) | ✗ Lebih lambat (matematika RSA) |
| Paling cocok untuk | Alat internal, API layanan tunggal | API produksi, sistem terdistribusi, OIDC |
Serangan kebingungan algoritma - dan cara mencegahnya
Kebingungan algoritma terjadi ketika server membaca field `alg` dari header JWT untuk memutuskan cara memverifikasi token, alih-alih menegakkan algoritma dari konfigurasinya sendiri. Penyerang mengubah header dari `RS256` menjadi `HS256`, lalu menandatangani token dengan kunci publik server yang dipakai sebagai secret HMAC. Server yang salah konfigurasi menerimanya sebagai valid. Perbaikannya hanya satu baris kode - tetapi harus ada.
// ✗ Vulnerable - algorithm inferred from token header
jwt.verify(token, publicKey);
// ✓ Correct - algorithm enforced from server configuration
jwt.verify(token, publicKey, { algorithms: ['RS256'] });Warning
Validasi kekuatan kunci untuk HS256
Saat memakai HS256, secret harus minimal 256 bit (32 byte) agar sesuai ukuran keluaran SHA-256. Secret pendek - kurang dari 32 karakter, kata kamus, atau string statis seperti `"secret"` atau `"development"` - mudah dipecahkan dengan brute force oleh alat seperti `hashcat` atau `jwt_tool`. Buat secret dengan sumber acak yang aman secara kriptografis: `crypto.randomBytes(32).toString('hex')` di Node.js menghasilkan string heksadesimal 64 karakter yang memenuhi syarat entropi minimum.
Memvalidasi claim JWT standar di TypeScript
Spesifikasi JWT mendefinisikan sejumlah claim terdaftar standar yang harus dipahami setiap implementasi. Pustaka `jsonwebtoken` memvalidasi beberapa di antaranya secara otomatis ketika Anda memberikan opsi yang tepat - tetapi kuncinya pada "ketika Anda memberikannya". Tanpa konfigurasi eksplisit, sebagian besar pemeriksaan claim dilewati diam-diam.
Claim exp, nbf, dan iat
Claim exp (kedaluwarsa) adalah stempel waktu Unix setelah itu token tidak lagi valid. Pustaka jsonwebtoken memeriksa exp secara default selama jwt.verify(). Namun, perbedaan jam antara penerbit token dan verifikator bisa membuat token valid ditolak - penyebab umum kesalahan "token kedaluwarsa" pada sistem terdistribusi yang jam servernya bergeser beberapa detik. Berikan clockTolerance agar ada jendela kecil: menetapkan clockTolerance 30 menerima token hingga 30 detik setelah nilai exp-nya.
interface JwtPayload {
sub: string;
iss: string;
aud: string;
exp: number;
iat: number;
role: 'admin' | 'user';
}
const payload = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://auth.example.com',
audience: 'api.example.com',
clockTolerance: 30, // seconds of clock skew to tolerate
}) as JwtPayload;Claim iss dan aud
Claim `iss` (penerbit) mengidentifikasi asal token. Claim `aud` (audiens) mengidentifikasi penerima yang dituju. Keduanya opsional dalam spesifikasi JWT tetapi krusial dalam praktik. Tanpa validasi `iss`, layanan mana pun yang mampu menghasilkan token valid dengan kunci penandatanganan Anda dapat mengautentikasi diri ke API Anda. Tanpa validasi `aud`, token yang diterbitkan untuk aplikasi seluler Anda dapat diputar ulang ke API admin Anda. Berikan keduanya sebagai opsi pada `jwt.verify()` agar pustaka menegakkannya sebagai persyaratan ketat, bukan sekadar field informatif.
Tip
Mengimplementasikan validasi JWT di TypeScript
Fungsi verifikasi JWT yang lengkap di TypeScript menangani validasi kriptografis, validasi claim, dan klasifikasi kesalahan dalam satu tempat. Begini cara menyusunnya - dengan empat langkah yang sesuai skema HowTo.
Pastikan algoritma cocok dengan jenis kunci Anda
Sebelum menulis kode verifikasi apa pun, konfirmasikan kombinasi algoritma dan kunci Anda. RS256 membutuhkan kunci privat RSA untuk menandatangani dan kunci publik terkait untuk memverifikasi. HS256 membutuhkan secret bersama yang sama di kedua sisi. Mencampurnya memicu pengecualian runtime yang sulit didiagnosis. Simpan kunci publik atau secret bersama di variabel lingkungan - jangan pernah meng-hardcode-nya di berkas sumber.
Validasi claim exp dan nbf secara eksplisit
Selalu atur `clockTolerance` untuk menangani pergeseran jam kecil antar layanan. Nilai 30 detik adalah default yang wajar untuk sebagian besar sistem terdistribusi. Saat mendebug `TokenExpiredError` di produksi, catat `payload.exp * 1000` dan `Date.now()` bersamaan - ini menunjukkan persis berapa milidetik token melewati kedaluwarsa, membedakan kedaluwarsa nyata dari masalah sinkronisasi jam antara layanan autentikasi dan server API Anda.
Periksa claim iss dan aud terhadap nilai yang diharapkan
Berikan opsi `issuer` dan `audience` ke `jwt.verify()` agar pustaka menolak token dengan nilai yang tidak cocok sebelum kode aplikasi Anda berjalan. Jika sistem Anda punya beberapa audiens yang valid (misalnya `api.example.com` dan `admin.example.com`), berikan array: `audience: ['api.example.com', 'admin.example.com']`. Pustaka menerima token jika claim `aud` cocok dengan salah satu entri array.
Uji konfigurasi Anda dengan Decoder JWT
Sebelum menjalankan suite pengujian TypeScript, tempelkan contoh token dari lingkungan development atau staging Anda ke Decoder & Validator JWT. Konfirmasikan secara visual bahwa setiap claim - `alg`, `exp`, `iss`, `aud`, dan claim kustom Anda - cocok dengan opsi `jwt.verify()` Anda. Pemeriksaan satu menit ini menangkap ketidaksesuaian antara isi token dan ekspektasi kode Anda sebelum menghabiskan waktu untuk debugging di lingkungan uji.
Decoder & Validator JWT
Dekode token JWT dan periksa semua claim, field header, serta masalah keamanan umum secara instan di browser Anda - tanpa pendaftaran, tanpa unggahan ke server.
Kesalahan konfigurasi JWT yang umum
Inilah kesalahan konfigurasi yang paling sering muncul dalam implementasi JWT TypeScript. Masing-masing senyap saat start dan hanya terwujud sebagai kegagalan autentikasi atau insiden keamanan di produksi.
Memakai `jwt.decode()` alih-alih `jwt.verify()`
Fungsi `jwt.decode()` mengekstrak payload tanpa memverifikasi tanda tangan. Ia berguna untuk menginspeksi token yang sudah Anda percayai - misalnya mengekstrak ID pengguna dari token yang telah divalidasi middleware. Ia bukan pengganti `jwt.verify()`. Kode yang memakai `jwt.decode()` untuk memperoleh claim lalu membuat keputusan otorisasi berdasarkan claim tersebut sedang menerima token yang belum terverifikasi. Ini bypass autentikasi total.
Mengabaikan jenis error di blok catch
Pustaka `jsonwebtoken` melempar tiga jenis error berbeda: `JsonWebTokenError` (token cacat atau tanda tangan tidak valid), `TokenExpiredError` (melewati claim `exp`), dan `NotBeforeError` (sebelum claim `nbf`). Menangkap semua error sebagai `Error` generik dan mengembalikan `401 Unauthorized` untuk semua kasus akan menghilangkan informasi diagnostik. Tangani tiap jenis secara terpisah dan kembalikan pesan spesifik - `token kedaluwarsa` versus `token tidak valid` - agar klien dan sistem pemantauan dapat membedakan masalah konfigurasi dari upaya serangan sungguhan.
Tidak merotasi secret atau pasangan kunci
Secret penandatanganan berumur panjang mengumpulkan risiko seiring waktu. Secret yang belum pernah dirotasi berarti setiap token yang pernah diterbitkan dengannya tetap valid bila secret terkompromi. Implementasikan field ID kunci (`kid`) di header JWT Anda agar verifikator dapat mencari kunci publik yang benar dari endpoint JWKS. Pola ini memungkinkan rotasi kunci tanpa membatalkan token yang ditandatangani kunci sebelumnya - setiap token membawa referensi ke kunci spesifik yang menandatanganinya. JWK Inspector membantu memvalidasi keluaran endpoint JWKS dan mendeteksi materi kunci privat yang seharusnya tidak diekspos publik.
Warning
Menerima algoritma `none`
Algoritma `none` menghasilkan JWT tanpa tanda tangan - payload apa pun dengan struktur valid lolos verifikasi. Versi pustaka JWT awal menerima `none` secara default. Pustaka modern menolaknya, tetapi hanya ketika Anda secara eksplisit menentukan algoritma yang diizinkan pada opsi verifikasi. Selalu sertakan `algorithms: ['RS256']` (atau algoritma spesifik Anda) agar penolakan `none` menjadi eksplisit dan tahan terhadap perubahan versi pustaka.
Mendebug masalah JWT dengan alat peramban
Menulis tes untuk mereproduksi error JWT sering kali lebih lambat daripada menginspeksi token secara langsung. Alat berbasis browser memungkinkan Anda memeriksa claim, status kedaluwarsa, dan struktur kunci token dalam hitungan detik - tanpa lingkungan lokal, tanpa menjalankan kode, dan tanpa mengunggah data sensitif ke layanan pihak ketiga.
Mendekode dan menginspeksi claim
Decoder & Validator JWT mendekode header dan payload string JWT apa pun serta menyajikan semua claim dalam format terstruktur dan mudah dibaca. Ia memeriksa masalah keamanan umum - `exp` hilang, algoritma lemah, `aud` hilang - dan menandainya dengan diagnostik yang jelas. Tempelkan token dari lingkungan development, staging, atau produksi Anda dan pastikan dalam sepuluh detik apakah claim-nya cocok dengan ekspektasi pemanggilan `jwt.verify()` Anda.
Mendiagnosis masalah kedaluwarsa
Kalkulator Hitung Mundur Kedaluwarsa JWT membaca claim `exp` dari token mana pun dan menampilkan sisa masa pakai persis atau waktu sejak kedaluwarsa baik dalam UTC maupun waktu lokal. Ketika pengguna melaporkan "token kedaluwarsa" tetapi log Anda menunjukkan token seharusnya masih valid, tempelkan ke kalkulator. Perbandingan stempel waktu presisi milidetik mengungkap apakah masalahnya kedaluwarsa sungguhan, pergeseran jam antar layanan, atau nilai `exp` yang tersimpan dalam milidetik alih-alih detik - bug faktor-1000 yang tak kira-kira sering terjadi.
Menginspeksi kumpulan kunci JWKS
Saat memvalidasi token dari penyedia OIDC atau layanan mana pun yang menerbitkan endpoint JWKS, JWK Inspector mengurai dan memvalidasi struktur kumpulan kunci. Ia memastikan setiap kunci memiliki field wajib (`kty`, `use`, `alg`, `kid`), memvalidasi jenis kunci dan kurva untuk kunci EC, serta menandai materi kunci privat yang seharusnya tidak diekspos publik. Tempelkan JSON dari endpoint JWKS Anda langsung ke alat ini atau berikan URL untuk diambil.
Kalkulator Hitung Mundur Kedaluwarsa JWT
Hitung mundur kedaluwarsa JWT secara persis dari claim exp - lihat sisa waktu atau waktu sejak kedaluwarsa dalam UTC dan waktu lokal, tanpa kode.
Praktik terbaik validasi JWT
Fungsi verifikasi JWT yang dikonfigurasi dengan benar memang diperlukan, tetapi belum cukup untuk autentikasi yang aman. Praktik-praktik berikut melengkapi gambaran untuk layanan TypeScript produksi.
Gunakan antarmuka payload bertipe
Definisikan antarmuka TypeScript untuk payload JWT Anda dan lakukan cast hasil verifikasi ke antarmuka itu. Ini memberi keamanan saat kompilasi atas nama claim dan jenis nilai - nama claim salah tulis (`userId` vs `user_id`) menjadi kesalahan TypeScript alih-alih `undefined` senyap saat runtime. Simpan antarmuka di modul tipe bersama agar konsisten di semua layanan yang memverifikasi format token yang sama.
Umur token pendek dengan refresh token
Token akses sebaiknya berumur pendek - 15 menit sampai 1 jam untuk sebagian besar API. Token akses berumur panjang (hari, minggu) memperluas jendela ketika token yang terkompromi masih bisa dipakai. Gunakan alur refresh token terpisah dengan kedaluwarsa panjang untuk persistensi sesi. Refresh token dirotasi setiap pemakaian, dan daftar pencabutan hanya diperlukan untuk refresh token - bukan token akses - selama umurnya dijaga pendek.
Sentralisasi logika verifikasi
Tulis verifikasi JWT di satu tempat - fungsi middleware atau utilitas bersama - dan gunakan di mana-mana. Logika verifikasi yang terduplikasi mengundang penyimpangan konfigurasi: satu endpoint memeriksa `aud`, yang lain lupa, dan inkonsistensinya dieksploitasi sebelum ada yang sadar. Middleware Express, guard NestJS, dan route handler Next.js semuanya punya pola rapi untuk mensentralisasi pemeriksaan autentikasi. Letakkan opsi `algorithms`, `issuer`, dan `audience` Anda dalam satu objek konfigurasi yang diimpor di seluruh codebase.
Konfigurasikan verifikasi sekali, tegakkan di mana-mana. Satu-satunya opsi JWT yang boleh berbeda antar endpoint adalah audiens yang diharapkan.
Tip
Key takeaways
- Selalu berikan `algorithms: ['RS256']` (atau algoritma spesifik Anda) secara eksplisit ke `jwt.verify()` - jangan biarkan pustaka menebaknya dari header token.
- Validasi claim `iss` dan `aud` di setiap pemanggilan verifikasi; menghilangkannya memungkinkan token dari layanan lain mengautentikasi ke API Anda.
- Gunakan `clockTolerance` untuk menangani pergeseran jam antar layanan terdistribusi, dan catat stempel waktu `exp` bersama `Date.now()` saat mendebug kesalahan kedaluwarsa.
- Jangan pernah memakai `jwt.decode()` untuk keputusan otorisasi - ia melewatkan verifikasi tanda tangan sepenuhnya dan menerima payload token apa pun.
- Decoder & Validator JWT memungkinkan Anda menginspeksi semua claim dan menandai masalah konfigurasi dalam hitungan detik, tanpa menulis atau menjalankan kode.
- RS256 lebih disarankan daripada HS256 untuk API produksi - menghilangkan risiko distribusi secret bersama dan mendukung rotasi kunci berbasis JWKS.
- Jaga umur token akses tetap pendek (15-60 menit) dan sentralisasi seluruh logika verifikasi dalam satu middleware atau utilitas untuk mencegah penyimpangan konfigurasi.