Skip to content
Kembali ke Blog
Keamanan

Cara Decode Token JWT: Panduan Lengkap untuk Developer

Pelajari cara decode token JWT dengan aman di browser, Node.js, Python, dan Go. Periksa header, payload, dan claims dengan JWT decoder online gratis 100% privat.

12 menit membaca

Cara Decode Token JWT: Panduan Lengkap untuk Developer

API Anda baru saja mengembalikan 401 Unauthorized. Header Authorization: Bearer eyJhbGciOi... terlihat baik-baik saja. Apakah token-nya sudah kedaluwarsa, audience-nya salah, atau issuer merotasi kunci? Anda tidak bisa menjawab pertanyaan itu tanpa membaca isi sebenarnya dari token tersebut, dan untuk decode token JWT, Anda tidak memerlukan secret, library, atau bahkan koneksi jaringan. JWT adalah tiga bagian yang di-encode dengan base64url dan disambung dengan titik. Proses decode-nya mekanis: split, base64url, JSON.parse. Tidak ada operasi kriptografi di dalamnya.

Panduan ini membahas anatomi JWT, menunjukkan cara decode JWT di Node.js, Python, Go, dan browser, menjelaskan perbedaan decode vs verify yang sering disalahpahami tim, serta mencantumkan mode kegagalan nyata yang akan Anda temui. Jika Anda hanya perlu memeriksa token sekarang juga, langsung ke JWT decoder gratis kami. Decoder ini berjalan sepenuhnya di browser Anda, jadi token produksi tidak pernah meninggalkan perangkat Anda.

Apa itu JWT? (anatomi singkat)

JSON Web Token (JWT) adalah kredensial yang kompak dan URL-safe, didefinisikan dalam RFC 7519. JWT membawa claims, yaitu data tentang pengguna dan token itu sendiri, antara dua pihak. JWT terdiri dari tiga potongan yang di-encode base64url dan disambung dengan titik: header, muatan (payload), dan tanda tangan (signature).

Berikut token nyata yang dipecah agar Anda dapat melihat strukturnya:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9       ← header
.
eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0   ← payload
.
4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0       ← signature

Header menjelaskan bagaimana token ditandatangani, biasanya { "alg": "HS256", "typ": "JWT" }. Payload (muatan) membawa claims, baik yang terdaftar seperti sub, exp, iat maupun yang kustom seperti role atau tenant. Signature (tanda tangan) adalah bukti kriptografis yang dihitung atas header dan payload, yang memungkinkan penerima mendeteksi manipulasi. Base64url adalah varian base64 yang URL-safe; baca panduan Base64 ramah pemula untuk pengantar sepuluh menit.

Anda akan bertemu JWT di mana pun sistem autentikasi modern bekerja: token akses OAuth 2.0, token ID OpenID Connect, kredensial API yang diterbitkan Auth0, Okta, Clerk, Supabase, Firebase, dan token yang dioper antar microservice di dalam sebuah mesh. Ini adalah format kredensial default selama satu dekade terakhir.

Sebelum melangkah lebih jauh, satu kalimat yang wajib Anda ingat: JWT di-encode, bukan dienkripsi. Siapa pun yang memegang token dapat membaca setiap claim. Tanda tangan membuktikan asal; ia tidak menyembunyikan isi. Fakta tunggal ini menentukan segala hal selanjutnya dalam panduan ini, yaitu apa yang aman diletakkan di payload, mengapa decoding tidak perlu secret, dan mengapa verifikasi tanda tangan wajib dilakukan di sisi server.

Cara kerja JWT decoding (base64url, bukan dekripsi)

Decoding JWT bukan operasi kriptografis. Ini adalah empat langkah mekanis:

  1. Pecah token pada . menjadi tepat tiga segmen.
  2. Decode base64url segmen pertama dan parse sebagai JSON. Itulah header.
  3. Decode base64url segmen kedua dan parse sebagai JSON. Itulah payload.
  4. Biarkan segmen ketiga (signature) sebagai byte mentah. Untuk memverifikasinya Anda memerlukan kunci.

Itulah keseluruhan algoritmanya. Tidak ada library yang wajib. Bahasa apa pun dengan base64 dan parser JSON dapat decode JWT dalam lima baris. Encoder/decoder Base64 kami akan menjalankan langkah 2 dan 3 secara manual jika Anda ingin melihat mekanismenya.

Apa itu base64url?

Base64url adalah base64 biasa dengan tiga penyesuaian agar output aman di URL dan header HTTP: - menggantikan +, _ menggantikan /, dan padding = di akhir dibuang. Jika Anda memberikan base64url mentah ke decoder base64 standar tanpa membalik substitusi tersebut, Anda mendapatkan hasil sampah atau error. Panduan Base64 lanjutan membahas kasus tepi padding secara mendalam.

Base64 standarbase64url
AlfabetA-Z a-z 0-9 + /A-Z a-z 0-9 - _
PaddingWajib = di akhirDibuang
Aman di URL?TidakYa
ContohPDw/Pz8+PDw_Pz8-

Satu catatan lagi yang layak ditonjolkan: Anda tidak bisa mendekripsi signature di sisi klien. Decoding bersifat satu arah dari byte ter-encode menuju JSON. Memverifikasi signature adalah operasi terpisah yang memerlukan secret HMAC (untuk algoritma keluarga HS) atau kunci publik issuer (untuk RS, PS, ES, EdDSA).

Mengapa Anda tidak perlu secret untuk decode

Karena payload adalah base64url plus JSON, bukan ciphertext. Secret baru masuk gambar ketika Anda ingin membuktikan token belum dimanipulasi, yaitu pemeriksaan signature. Siapa pun di jalur jaringan, siapa pun yang memegang token di baris log, siapa pun dengan browser dapat membaca setiap claim yang Anda taruh di dalamnya. Karena itu Anda tidak boleh memasukkan password, API key, atau PII di luar yang sudah diketahui penerima ke dalam payload JWT. Untuk model ancaman yang lebih luas, baca panduan praktik keamanan terbaik kami.

Decode JWT online dalam 3 klik — JWT decoder gratis

Kadang Anda butuh jawaban sekarang juga. Apakah token ini kedaluwarsa, apakah claim aud sesuai dugaan saya, apakah header menyatakan alg:none? Jalur tercepat adalah JWT decoder online kami. Decoder ini dibangun untuk jalur respons insiden jam 2 pagi.

  1. Tempelkan token lengkap ke area input. Sertakan ketiga segmen yang dipisahkan titik.
  2. Baca header dan payload yang sudah di-decode, serta chip status di bagian atas: algoritma, issued-at, expiration, dan lencana merah Expired jika exp sudah lewat.
  3. Salin panel mana pun yang Anda butuhkan ke bug report, thread Slack, atau test fixture Anda.

Mengapa aman untuk token produksi nyata:

  • 100% berbasis browser. Decoding berjalan lewat atob dan JSON.parse native. Tidak ada request jaringan, sama sekali.
  • Tanpa logging, tanpa tracking, tanpa cookie, tanpa signup.
  • Bisa dipakai offline begitu halaman selesai dimuat.

Tool JWT Decoder bersifat algorithm-agnostic. Karena decoding hanya perlu base64url dan JSON, ia membaca setiap varian JWS: HS256/384/512, RS256/384/512, PS256/384/512, ES256/384/512, EdDSA, dan alg:none. Hanya verifikasi signature yang bergantung pada algoritma, dan verifikasi bukan hal yang sebaiknya dilakukan oleh tool web publik. Sebentar lagi kita bahas.

Perlu decode base64 sebuah segmen secara manual untuk memeriksa silang hasil tool? Gunakan Encoder/decoder Base64 kami dan masukkan tiap segmen sebagai base64url.

Cara decode JWT dalam kode (Node.js, Python, Go, Browser)

Untuk segala yang bukan debugging interaktif, seperti middleware, pengujian, script migrasi, atau tool CLI, Anda akan meraih sebuah library. Berikut kode minimum untuk decode JWT di empat lingkungan yang paling mungkin Anda temui, dengan jalur read-only dan jalur verifikasi berdampingan. Setiap cuplikan bisa langsung disalin-tempel dan menghasilkan output seperti pada komentar.

Decode JWT di Node.js (jsonwebtoken)

// npm install jsonwebtoken
const jwt = require('jsonwebtoken');

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9' +
              '.eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0' +
              '.4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0';

// Hanya decode — TIDAK memverifikasi signature
const decoded = jwt.decode(token, { complete: true });
console.log(decoded.header);   // { alg: 'HS256', typ: 'JWT' }
console.log(decoded.payload);  // { sub: 'user_123', exp: 1999999999 }

// Verifikasi — jalur produksi
const secret = process.env.JWT_SECRET;
const verified = jwt.verify(token, secret, { algorithms: ['HS256'] });

Selalu kirim allowlist algorithms yang eksplisit ke verify. Secara historis, menghilangkannya membiarkan penyerang menurunkan token RS256 menjadi HS256 dengan menandatangani menggunakan kunci publik sebagai secret HMAC, yaitu serangan algorithm-confusion yang sudah lama dikenal. Allowlist adalah pertahanan Anda.

Decode JWT di Python (PyJWT)

# pip install PyJWT
import jwt

token = (
    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
    ".eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0"
    ".4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0"
)

# Hanya decode — tidak aman untuk auth, oke untuk inspeksi
decoded = jwt.decode(token, options={"verify_signature": False})
print(decoded)  # {'sub': 'user_123', 'exp': 1999999999}

# Header tanpa menyentuh payload
header = jwt.get_unverified_header(token)
print(header)   # {'alg': 'HS256', 'typ': 'JWT'}

# Verifikasi — jalur produksi
payload = jwt.decode(
    token,
    key="your-hs256-secret",
    algorithms=["HS256"],
    audience="api.example.com",
)

PyJWT menolak memverifikasi tanpa daftar algorithms. Default yang masuk akal, dan mencegah serangan confusion yang sama seperti peringatan di contoh Node di atas.

Decode JWT di Go (golang-jwt/jwt/v5)

// go get github.com/golang-jwt/jwt/v5
package main

import (
    "fmt"
    "github.com/golang-jwt/jwt/v5"
)

func main() {
    tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +
        ".eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0" +
        ".4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0"

    // Hanya decode
    parser := jwt.NewParser()
    claims := jwt.MapClaims{}
    _, _, err := parser.ParseUnverified(tokenString, claims)
    if err != nil {
        panic(err)
    }
    fmt.Println(claims["sub"], claims["exp"]) // user_123 1.999999999e+09

    // Verifikasi
    secret := []byte("your-hs256-secret")
    token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
        if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected alg: %v", t.Header["alg"])
        }
        return secret, nil
    })
    fmt.Println(token.Valid, err)
}

Closure keyFunc adalah tempat Anda memaksakan keluarga algoritma: tolak apa pun yang bukan method yang Anda harapkan sebelum mengembalikan kunci.

Decode JWT di browser (tanpa dependency)

Kadang Anda tidak mau dependency sama sekali, misalnya panel debug cepat, ekstensi browser, atau lencana UI kecil yang menampilkan role pengguna saat ini. API native browser sudah cukup:

function decodeJwt(token) {
  const [h, p] = token.split('.');
  const pad = (s) => s + '==='.slice((s.length + 3) % 4);
  const decodeSegment = (s) => {
    const b64 = pad(s).replace(/-/g, '+').replace(/_/g, '/');
    const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
    return JSON.parse(new TextDecoder().decode(bytes));
  };
  return { header: decodeSegment(h), payload: decodeSegment(p) };
}

const { header, payload } = decodeJwt(token);
console.log(header);   // { alg: 'HS256', typ: 'JWT' }
console.log(payload);  // { sub: 'user_123', exp: 1999999999 }

Langkah TextDecoder penting untuk token apa pun yang payload-nya mengandung non-ASCII (emoji di nama tampilan, huruf Kiril di preferred_username). atob biasa mengembalikan string biner, yang mematahkan JSON.parse pada UTF-8 multi-byte. Ini persis yang dijalankan JWT decoder online kami secara lokal di browser Anda, tanpa UI.

Tabel perbandingan

BahasaDecode sajaVerifikasiLibrary
Node.jsjwt.decode(token)jwt.verify(token, key, { algorithms: [...] })jsonwebtoken
Pythonjwt.decode(token, options={"verify_signature": False})jwt.decode(token, key, algorithms=[...])PyJWT
Goparser.ParseUnverified(token, claims)jwt.Parse(token, keyFunc)golang-jwt/jwt/v5
Browseratob + TextDecoder + JSON.parseTanyakan ke backend Anda

Decode vs verify — perbedaan krusial

Decoding JWT membaca claims-nya; verifying JWT membuktikan claims tersebut belum dimanipulasi. Decoding tidak pernah mempercayai; verifikasi adalah tindakan percaya. Inilah satu pembeda yang memisahkan implementasi auth yang benar dari sebuah CVE.

DecodeVerify
Butuh secret/kunci?TidakYa
Jalan di sisi klien?AmanTidak pernah
Membuktikan keaslian?TidakYa
Memeriksa expiration?OpsionalYa
Use caseDebugging, inspeksiAutentikasi, otorisasi

Jangan pernah membuat keputusan otorisasi dari JWT yang sudah di-decode (belum diverifikasi). Bukan di middleware, bukan di React hook, bukan di serverless function yang Anda kira berada di balik gateway. Claims yang di-decode menyatakan apa yang diklaim token, sementara claims yang diverifikasi menyatakan apa yang ditandatangani issuer. Penyerang yang menyerahkan token buatan tangan tanpa signature valid ke server Anda bisa memasukkan apa saja di payload; hanya pemeriksaan signature yang akan menolaknya.

Satu detail krusial lagi soal keluarga HMAC: jika Anda menggunakan HS256, entropi secret Anda menentukan segalanya. Secret pendek dan mudah ditebak akan dibobol secara offline terhadap token apa pun yang berhasil disadap penyerang. Setelah itu mereka mencetak token sendiri dan masuk lewat pintu depan. Gunakan setidaknya 256 bit keacakan nyata. Lihat panduan kekuatan secret HMAC kami untuk perhitungan mengapa ini penting.

Referensi claim JWT umum

Setiap JWT yang Anda temui menggunakan sebagian dari claims terdaftar dari RFC 7519. Hafalkan daftar singkatnya:

ClaimNamaContohCatatan
issIssuerhttps://auth.example.comSiapa yang mencetak token
subSubjectuser_123Biasanya ID pengguna
audAudienceapi.example.comUntuk siapa token ditujukan; wajib cocok di server
expExpiration1715003600Detik Unix; di masa lalu = kedaluwarsa
iatIssued At1715000000Detik Unix saat token dicetak
nbfNot Before1715000060Waktu paling awal token bisa dipakai
jtiJWT IDd1f8…Unik per token; mencegah replay
kidKey ID (header)key-2025-01Kunci mana di JWKS Anda yang menandatanganinya

Claim khusus aplikasi duduk berdampingan: role, scope, email, tenant_id, apa pun yang dikeluarkan identity provider Anda. Jaga agar tetap ringkas, karena setiap byte ikut membonceng di setiap request.

Untuk membaca tanggal manusiawi dari iat dan exp, coba konverter Unix timestamp kami. Tempel angkanya, dapatkan tanggal di zona waktu lokal Anda, dan temukan bug skew dalam sedetik.

Troubleshooting — mengapa JWT saya tidak bisa di-decode?

Lima mode kegagalan nyata, secara kasar diurutkan berdasarkan frekuensi. Tiap poin dibingkai Gejala → Penyebab → Perbaikan.

  1. “Format JWT tidak valid — harus tiga segmen.” Anda hanya menyalin payload, atau shell melipat token lintas baris dan Anda hanya mengambil baris pertama. Perbaikan: salin ulang nilai lengkap xxx.yyy.zzz dari response body asli, bukan dari terminal yang sudah di-render. Nilai satu-baris yang panjang lebih aman di tab Network pada devtools browser dibanding di terminal yang di-scroll.
  2. Lima segmen, bukan tiga. Yang Anda punya adalah JWE (JWT terenkripsi), bukan JWS. Formatnya header.encryptedKey.iv.ciphertext.tag. Decoder akan membaca header tetapi payload-nya adalah ciphertext. Perbaikan: decoding payload butuh kunci dekripsi, yang biasanya ditangani di server oleh SDK auth Anda, bukan tool debug.
  3. Error base64url pada token yang kelihatannya valid. Token itu sempat di-URL-encode di suatu titik salin (cookie, URL redirect, log proxy tersadap). Anda akan melihat %2E atau %2B literal di string. Perbaikan: URL-decode dulu, lalu masukkan hasilnya ke JWT decoder.
  4. Error parse JSON di payload. Sebuah terminal atau klien chat menyisipkan newline soft-wrap, atau sebuah script menempelkan smart quote di sekeliling identifier. Perbaikan: lihat byte mentah response (curl dengan -o file.txt, atau tampilan Raw di devtools), bersihkan whitespace, tempel ulang.
  5. Decode bersih tapi backend tetap menolaknya. Bukan masalah decoding, melainkan masalah verifikasi. Token secara struktur valid; ada sesuatu yang diperiksa server (signature, aud, exp, clock skew, lookup kid) yang gagal. Loncat ke bagian berikutnya.

Dua honorable mention yang bukan error parse tetapi layak ditangkap selagi decoder terbuka: nilai alg none di header (perlakukan sebagai bermusuhan di produksi) dan nilai exp yang sudah lewat (decoder tetap menampilkan claims agar Anda bisa debug. Itu perilaku yang benar, dan tool kami menandainya dengan lencana merah Expired).

Ketika decoding belum cukup — verifikasi signature

Decoding berhenti di “inilah yang diklaim token.” Verifikasi adalah yang mengubah klaim menjadi keputusan kepercayaan. Signature adalah bukti, dihitung dengan kunci privat issuer atau secret bersama, yang mengikat header dan payload; ubah satu byte saja dan pemeriksaan signature gagal. Tanpa pemeriksaan itu, siapa pun yang bisa melakukan POST ke endpoint Anda dapat merakit token “admin” dengan mengedit payload dan melewati signature sama sekali.

Jangan pernah menerima alg:none.

Verifikasi produksi, di setiap bahasa dan framework, kira-kira mengikuti checklist ini. Perlakukan item yang hilang sebagai bug:

  • Kirim allowlist algorithms: ['RS256'] yang eksplisit (atau apa pun yang Anda pakai). Ini mengalahkan serangan algorithm-confusion.
  • Verifikasi aud cocok dengan identifier layanan Anda dan iss cocok dengan URL issuer yang Anda harapkan.
  • Periksa exp terhadap waktu saat ini dengan toleransi clock-skew maksimal 60 detik.
  • Saat rotasi kunci, cari kunci publik berdasarkan kid dari endpoint JWKS; jangan hardcode satu kunci selamanya.
  • Revoke secara efektif dengan menjaga exp singkat (menit, bukan hari) dan secara opsional memelihara denylist jti untuk token bernilai tinggi.

Setiap library JWT arus utama memaparkan ini sebagai opsi dalam satu pemanggilan. Jika kode verifikasi Anda tidak menyetelnya, Anda membiarkan default menyala, dan default-lah yang secara historis menjadi sumber bug. Untuk model ancaman lengkap, lihat panduan praktik keamanan terbaik kami.

FAQ

Bisakah saya decode JWT tanpa secret key?

Bisa. Header dan payload di-encode base64url, bukan dienkripsi; siapa pun yang memegang token dapat membaca claims-nya. Secret atau kunci publik hanya diperlukan untuk memverifikasi signature. Ini by design: payload memang dimaksudkan agar bisa dibaca supaya penerima dapat mengambil keputusan otorisasi.

Apakah aman menempelkan JWT produksi saya ke decoder online?

Hanya jika decoder berjalan di browser Anda dan tidak pernah mengunggah token. JWT Decoder kami melakukan parsing secara lokal dengan atob dan JSON.parse native, sehingga tidak ada yang dikirim ke server mana pun. Debugger remote yang melakukan POST token Anda ke sebuah API harus dianggap sebagai kebocoran kredensial.

Apa beda decoding dan verifying JWT?

Decoding hanya membaca claims; tidak perlu kunci dan tidak membuktikan apa pun. Verifying memeriksa signature terhadap kunci issuer dan memastikan token belum dimanipulasi. Jangan pernah membuat keputusan autentikasi dari token yang sudah di-decode tetapi belum diverifikasi.

JWT saya terlihat terpotong — apa yang dianggap format valid?

JWT valid memiliki tepat tiga segmen base64url yang dipisahkan titik: header.payload.signature. Lima segmen berarti Anda memegang JWT terenkripsi (JWE), bukan JWS. Nol titik berarti Anda hanya menyalin satu segmen dari baris terminal yang dilipat.

Mengapa decoder masih menampilkan token yang kedaluwarsa?

Decoder membaca claims terlepas dari validitasnya agar Anda bisa men-debug penolakan. Hanya verifier yang menolak token kedaluwarsa. Tool kami memunculkan lencana Expired dengan membandingkan exp terhadap jam lokal Anda, sehingga Anda dapat langsung melihat masalahnya tanpa harus menyipitkan mata membaca Unix timestamp.

Algoritma apa saja yang bisa saya decode?

Semuanya. Decoding hanya perlu base64url dan parsing JSON, dan sifatnya algorithm-agnostic. Itu mencakup HS256/384/512, RS256/384/512, PS256/384/512, ES256/384/512, EdDSA, dan alg:none. Hanya verifikasi yang bergantung pada algoritma yang Anda pilih.

Sebaiknya pakai jwt-decode atau jsonwebtoken di Node.js?

Pakai jwt-decode di frontend ketika Anda hanya perlu membaca payload, misalnya menampilkan username dari access token. Pakai jsonwebtoken di backend, karena hanya backend yang boleh memegang kunci penandatangan dan menjalankan jwt.verify. Jangan pernah verifikasi di klien.

Kesimpulan

Decoding JWT jauh dari semisterius seperti yang disiratkan istilah “cryptographic token”. Pegang lima poin ini dan Anda tidak akan lagi terpaku menatap string eyJhbGciOi… yang buram:

  • Decoding adalah base64url plus JSON parse. Tanpa secret.
  • JWT punya tiga bagian (header, payload, signature) yang disambung titik.
  • Decoding tidak pernah membuktikan keaslian. Selalu verifikasi di sisi server dengan kunci issuer.
  • Tolak alg:none dan selalu kirim allowlist algoritma eksplisit ke verify.
  • Jangan pernah menyimpan password, kunci privat, atau PII sensitif di payload, karena isinya bisa dibaca siapa pun yang memegang token.

Simpan JWT decoder gratis kami untuk debugging on-call. Tempel token, baca claims, temukan expiry dalam sedetik, semuanya tanpa token Anda pernah meninggalkan browser.

Artikel Terkait

Lihat semua artikel