FlowingDev

JWT dijelaskan: token yang membawa paspornya sendiri

Mengenal JSON Web Tokens (JWT), standar ringkas dan mandiri untuk mengirimkan informasi secara aman antar pihak sebagai objek JSON.

Coba tool-nya: Penampil JWT

Dalam satu kalimat

JSON Web Token (JWT) adalah cara yang ringkas dan aman untuk URL untuk merepresentasikan 'klaim' yang akan ditransfer antara dua pihak, biasanya digunakan untuk autentikasi dan otorisasi dengan cara yang dapat diverifikasi dan dipercaya.

Masalah yang diselesaikan

Di zaman baheula—katakanlah, awal tahun 2000-an—kalau kamu login ke sebuah website, server akan membuat "session" untukmu. Ini seperti file kecil di server yang isinya, "User 123 sudah login dan menaruh ayam karet di keranjang belanjanya." Server akan memberikan browser-mu cookie kecil berisi ID sesi, ibarat tiket penitipan jaket. Di setiap request berikutnya, browser-mu menunjukkan tiket itu, server mencarinya, menemukan file-mu, dan ingat siapa kamu.

Ini berjalan baik untuk satu server monolitik. Tapi kemudian web meledak. Kita punya microservices, single-page applications (SPAs), dan aplikasi mobile yang semuanya berkomunikasi ke backend yang sama. Sekarang, request login-mu mungkin masuk ke Server A, tapi request berikutnya untuk mengambil profilmu bisa jadi masuk ke Server B. Bagaimana Server B tahu tentang file sesi di Server A?

Kamu bisa memaksa user untuk selalu berkomunikasi dengan server yang sama ("sticky sessions"), tapi itu jadi bottleneck. Kamu bisa membuat database sesi terpusat (seperti Redis) yang digunakan bersama oleh semua server, tapi itu nambahin infrastruktur lagi untuk dikelola dan satu titik kegagalan lagi.

Masalah intinya adalah statefulness. Server harus mengingatmu.

JWT (dibaca "jot") membalik ide ini. Bagaimana jika user bisa membawa bukti identitasnya sendiri, seperti paspor? Token itu sendiri akan berisi semua informasi yang dibutuhkan server: siapa user-nya, apa yang boleh mereka lakukan, dan kapan akses mereka berakhir. Server tidak perlu mengingat apa pun di antara request. Inilah autentikasi stateless, dan ini adalah kunci untuk membangun sistem terdistribusi yang skalabel. Server hanya perlu memeriksa apakah paspornya (JWT) valid dan tidak dipalsukan.

Cara kerjanya di balik layar

JWT bukanlah gumpalan omong kosong yang tidak bisa dipahami. Ini adalah string yang sangat spesifik dan terstruktur yang terdiri dari tiga bagian, dipisahkan oleh titik (.).

xxxxx.yyyyy.zzzzz

Mari kita bedah setiap bagian.

Header (Tag "Tipe")

Bagian pertama adalah header. Ini adalah objek JSON sederhana yang berisi metadata tentang token itu sendiri, terutama algoritma penandatanganan (signing) yang digunakan dan tipe tokennya.

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: Algoritma penandatanganan. HS256 berarti token ini ditandatangani dengan HMAC-SHA256, sebuah algoritma simetris (lebih lanjut tentang ini sebentar lagi). Opsi umum lainnya termasuk RS256 (menggunakan pasangan kunci publik/privat RSA).
  • typ: Tipe token. Untuk JWT, ini hanyalah "JWT".

JSON ini kemudian di-encode dengan Base64Url untuk menghasilkan bagian pertama dari token. Base64 adalah skema encoding, bukan enkripsi. Ia hanya mengubah data biner menjadi string teks yang aman untuk ditransmisikan melalui web. Anggap saja seperti menulis "INI KARTU POS" di belakang kartu pos—siapa pun yang menyadapnya bisa membacanya.

Payload (Departemen "Klaim")

Bagian kedua adalah payload. Di sinilah bagian serunya. Ini adalah objek JSON lain yang berisi "klaim", yaitu pernyataan tentang pengguna ("subjek") dan data berguna lainnya.

{
  "sub": "10987-23456-98765",
  "name": "Grace Hopper",
  "admin": true,
  "iat": 1516239022,
  "exp": 1516242622
}

Klaim ada tiga jenis:

  • Registered Claims: Ini adalah sekumpulan klaim yang telah ditentukan sebelumnya dan direkomendasikan untuk menyediakan interoperabilitas. Tidak wajib, tapi sangat berguna.
Klaim Nama Deskripsi
iss Issuer Siapa yang menerbitkan token (mis., https://api.mycoolsite.com).
sub Subject Pengguna atau entitas yang dimaksud oleh token (mis., ID pengguna).
aud Audience Untuk siapa token ini ditujukan (mis., https://api.mycoolsite.com).
exp Expiration Time Kapan token kedaluwarsa. Sebuah Unix timestamp numerik (detik sejak epoch).
iat Issued At Kapan token diterbitkan. Juga sebuah Unix timestamp.
  • Public Claims: Ini adalah klaim kustom yang kamu buat, tetapi untuk menghindari tabrakan nama, klaim ini harus didefinisikan dalam registri IANA JSON Web Token Claims atau berupa URI yang berisi namespace yang tahan-tabrakan (collision-resistant).
  • Private Claims: Ini adalah klaim kustom yang paling umum, dibuat untuk berbagi informasi antara pihak-pihak yang setuju untuk menggunakannya (seperti admin: true dalam contoh kita). Di sinilah kamu menempatkan data spesifik aplikasimu.

Sama seperti header, seluruh payload JSON di-encode dengan Base64Url untuk membentuk bagian kedua dari JWT. Sekali lagi, ini bukan enkripsi. Jangan pernah menaruh informasi sensitif seperti password di dalam payload.

Signature (Segel Anti-rusak)

Inilah bagian yang memberikan keamanan. Signature digunakan untuk memverifikasi bahwa pengirim JWT adalah benar-benar pihak yang dimaksud dan untuk memastikan bahwa pesan tidak diubah di tengah jalan.

Signature dibuat dengan mengambil header yang sudah di-encode, payload yang sudah di-encode, sebuah kunci rahasia (secret key), dan menjalankannya melalui algoritma yang ditentukan di header. Untuk contoh HS256 kita, prosesnya terlihat seperti ini:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  your-256-bit-secret
)

Intinya: sebuah secret digunakan yang hanya diketahui oleh server. Ketika server menerima JWT, ia akan menjalankan kembali perhitungan yang sama persis dengan header dan payload yang diterimanya. Jika signature yang dihasilkannya cocok dengan signature pada token, server tahu dua hal:

  1. Keaslian (Authenticity): Token dibuat oleh seseorang yang mengetahui secret key (yaitu, server itu sendiri).
  2. Integritas (Integrity): Header dan payload belum diubah. Jika penyerang mengubah "admin": false menjadi "admin": true" di payload, signature-nya tidak akan cocok lagi.

Signature ini adalah segel holografik anti-rusak pada paspor kita.

Cerita dari dunia nyata

Labirin Microservices

Sebuah perusahaan e-commerce yang berkembang pesat, "ScaleFast," memutuskan untuk memecah backend monolitiknya yang raksasa menjadi sekumpulan microservices: satu untuk user, satu untuk pesanan, satu untuk inventaris, dll. Sistem lama menggunakan sesi di sisi server. Tapi di dunia baru ini, bagaimana OrderService tahu bahwa sebuah request benar-benar datang dari user yang sudah login, tanpa harus memanggil UserService di setiap request? Itu akan lambat dan menggagalkan tujuan decoupling.

Solusinya adalah JWT. Ketika user login, AuthService yang baru akan menerbitkan JWT yang berisi userId dan roles mereka. Browser user kemudian menyertakan JWT ini di header Authorization pada setiap request ke microservice lain. OrderService dan InventoryService tidak perlu berbicara dengan AuthService; mereka hanya perlu mengetahui shared secret key. Mereka dapat secara independen memverifikasi signature JWT, mempercayai userId di dalamnya, dan memproses request.

Pelajaran: JWT adalah lingua franca dari autentikasi microservice, memungkinkan layanan menjadi stateless dan dapat diverifikasi secara independen.

Saga Single-Page App

Seorang developer bernama Alex sedang membangun dasbor React yang keren. Frontend-nya adalah Single-Page Application (SPA) yang disajikan dari host statis, dan berkomunikasi dengan API backend yang terpisah. Alex sedang bergelut dengan autentikasi berbasis cookie jadul, dan mengalami mimpi buruk masalah Cross-Origin Resource Sharing (CORS) karena frontend dan backend berada di domain yang berbeda.

Tim beralih ke JWT. Sekarang, setelah user login dengan username dan password mereka, API mengirimkan kembali sebuah JWT. Aplikasi React milik Alex menyimpan token ini di memori dan melampirkannya ke setiap panggilan API: Authorization: Bearer <the-jwt>. Backend API bersifat stateless; ia hanya memeriksa bearer token pada setiap request yang masuk. Tidak ada lagi pusing kepala karena cookie CORS.

Pelajaran: JWT menyediakan kredensial yang bersih dan portabel yang bekerja dengan sangat baik untuk memisahkan (decoupling) aplikasi frontend modern dari API backend.

Kesalahan dan jebakan umum

  • Menaruh data sensitif di payload. Stop! Payload itu di-encode dengan Base64Url, yang sangat mudah dibalikkan. Itu bukan enkripsi. Siapa pun yang mendapatkan token bisa membaca payload-nya. Anggap itu seperti kartu pos, bukan surat bersegel.
  • Lupa memverifikasi signature. Apa gunanya fitur keamanan paspor jika petugas perbatasan tidak memeriksanya? Hanya men-decode payload dan mempercayai isinya tanpa memverifikasi signature adalah kerentanan keamanan yang fatal. Penyerang bisa memalsukan payload apa pun yang mereka inginkan.
  • Mempercayai header alg secara membabi buta. Sebuah kerentanan terkenal di masa lalu melibatkan penyerang yang membuat token dan mengubah header menjadi {"alg": "none"}. Beberapa library yang salah konfigurasi akan melihat "none" dan "memverifikasi" signature dengan, yah, tidak melakukan apa-apa, lalu menerima token palsu tersebut sebagai valid. Selalu pastikan server-mu memberlakukan algoritma spesifik yang diharapkan (misalnya, HS256).
  • Membocorkan secret key simetris Anda. Untuk algoritma HMAC seperti HS256, secret key adalah kunci kerajaan. Jika bocor, siapa pun dapat memalsukan token untuk user mana pun dengan izin apa pun. Jaga seperti kamu menjaga password.
  • Tidak menyetel klaim kedaluwarsa (exp). Token yang hidup selamanya adalah liabilitas besar. Jika pernah disusupi, penyerang dapat menggunakannya tanpa batas waktu. Selalu atur waktu kedaluwarsa yang cukup singkat dan gunakan mekanisme refresh token untuk sesi yang lebih lama.

Kenapa ini perlu kamu tahu

Kamu harus berpikir "JWT" setiap kali berurusan dengan autentikasi atau otorisasi di lingkungan terdistribusi.

  • Kamu sedang membangun API untuk Single-Page App (SPA) atau klien mobile.
  • Kamu sedang merancang arsitektur microservice di mana layanan perlu saling mempercayai request satu sama lain.
  • Kamu butuh autentikasi stateless yang dapat di-scale secara horizontal tanpa penyimpanan sesi bersama (shared session store).
  • Kamu sedang mengimplementasikan alur otorisasi sekali pakai, seperti link reset password atau verifikasi email, di mana token yang mandiri dan dapat kedaluwarsa sangat cocok.

Ini adalah standar modern untuk merepresentasikan klaim secara aman, dan memahami kekuatan—serta kelemahannya—adalah hal yang tidak bisa ditawar bagi developer zaman sekarang.

Gali Lebih Dalam

  • RFC 7519: Spesifikasi resmi untuk JSON Web Token (JWT). Sumber kebenaran satu-satunya.
  • jwt.io: Sumber daya fantastis dengan debugger langsung dan daftar library untuk hampir semua bahasa.
  • OWASP JWT Cheat Sheet: Panduan penting untuk praktik terbaik keamanan dan jebakan dalam menggunakan JWT (nasihatnya bersifat agnostik-bahasa).
  • MDN Web Docs: Authorization header: Pelajari tentang skema autentikasi Bearer yang biasa digunakan untuk mengirimkan JWT.
  • Wikipedia: JSON Web Token: Gambaran umum tingkat tinggi yang bagus tentang konsep dan sejarahnya.

Teori beres. Saatnya praktik — 100% di browser kamu.

Coba tool-nya: Penampil JWT