Cara Decode dan Debug JWT
JSON Web Token hanyalah tiga bagian yang di-encode dengan Base64URL. Setelah kamu bisa membacanya, sebagian besar error “invalid token” bisa dipahami dalam hitungan detik. Panduan ini menunjukkan cara decode JWT, memeriksa claim yang paling sering bermasalah, serta kesalahan yang membuat JWT jadi celah keamanan.
Apa saja isi sebuah JWT
JWT terlihat seperti xxxxx.yyyyy.zzzzz. Ketiga bagian yang dipisahkan titik itu adalah:
- Header — JSON berisi algoritma penandatanganan (
alg) dan tipe token, misalnya{"alg":"HS256","typ":"JWT"}. - Payload — JSON berisi claim: token ini milik siapa dan kapan token berlaku.
- Signature — hash dari dua bagian pertama yang dibuat dengan secret (HMAC) atau private key (RSA, ECDSA).
Dua bagian pertama hanya di-encode, bukan dienkripsi. Siapa pun yang memegang token bisa membacanya, makanya jangan pernah memasukkan password atau data pribadi ke payload JWT.
Decode token
Tempel token ke JWT Decoder dan alat ini akan menampilkan header, payload, serta setiap timestamp dalam format tanggal yang mudah dibaca. Prosesnya berjalan di browser kamu, jadi token production tidak dikirim ke mana pun. Untuk melakukannya secara manual, decode tiap bagian dengan Base64URL — ganti - dengan +, _ dengan /, lalu tambahkan padding — atau di Node:
const [header, payload] = token.split('.').slice(0, 2)
.map(part => JSON.parse(Buffer.from(part, 'base64url').toString()));
console.log(header, payload);
Claim yang paling sering bermasalah
| Claim | Arti | Error yang umum |
|---|---|---|
exp | Kedaluwarsa, dalam detik Unix | “jwt expired” — periksa juga jam server dan client |
nbf | Belum berlaku sebelum waktu ini | Token dipakai beberapa detik lebih awal karena jam issuer berjalan lebih cepat |
iat | Diterbitkan pada | Ditolak sebagai “issued in the future” setelah clock drift |
aud | Audience yang dituju token | Token untuk satu API dikirim ke API lain — verifier wajib memeriksanya |
iss | Issuer | Issuer dev dan production tertukar |
Timestamp dihitung dalam detik, bukan milidetik. Jika expiry terlihat seperti tahun 55.000, berarti seseorang menulis Date.now() alih-alih Math.floor(Date.now() / 1000). Unix Timestamp Converter bisa memastikannya. Kebanyakan library menerima clock tolerance kecil (30–60 detik) untuk menyerap selisih jam antar server.
Kenapa muncul “invalid signature”?
- Secret atau key salah — penyebab paling umum. Periksa environment variable di server yang melakukan verifikasi, bukan hanya yang menandatangani.
- Algoritma salah — token ditandatangani dengan RS256 tapi diverifikasi sebagai HS256, atau sebaliknya.
- Token sudah diubah — mengubah satu karakter pada payload akan merusak signature, dan itulah tujuannya.
- Rotasi key — key issuer sudah berubah. Dengan JWKS, cocokkan
kiddi header dengan key yang dipublikasikan.
Untuk mengecek token HS256 secara manual, hitung HMAC-SHA256 atas header.payload dengan secret tersebut di HMAC Generator, lalu bandingkan hasilnya (yang sudah di-encode Base64URL) dengan bagian ketiga.
Kesalahan keamanan yang harus dihindari
- Decode bukan verifikasi. Jangan pernah percaya claim dari
jwt.decode(); gunakan fungsi verify dari library kamu dengan daftar algoritma yang diizinkan secara eksplisit. - Tolak
alg: nonedan kunci algoritmanya — jangan pernah biarkan token menentukan sendiri cara pengecekannya. - Buat token berumur pendek (beberapa menit untuk access token) dan gunakan refresh token untuk sesi panjang; JWT tidak bisa dicabut sebelum kedaluwarsa tanpa state tambahan di server.
- Jangan simpan token di localStorage jika ada bug XSS yang bisa membacanya; cookie HttpOnly, Secure, SameSite lebih aman untuk aplikasi browser.
Butuh token uji dengan claim tertentu? Buat dengan JWT Encoder.