Lewati ke isi

Keamanan/Cyber Security

Kesalahan Umum Memakai JWT untuk Login Aplikasi

Algoritma tidak dikunci, secret lemah, token berumur panjang, dan data sensitif di payload. Kenali kesalahan JWT yang umum dan cara memperbaikinya.

Terbit 6 menit baca

Jawaban singkat

Kesalahan JWT yang paling sering adalah tidak mengunci algoritma saat verifikasi, memakai secret HMAC yang lemah, memberi masa berlaku terlalu panjang tanpa cara mencabut, menaruh data sensitif di payload, dan lupa memeriksa klaim seperti exp, iss, dan aud.

Daftar isi
  1. Apa sebenarnya JWT itu?
  2. Kesalahan 1: menerima algoritma apa pun yang tertulis di header
  3. Kesalahan 2: secret HMAC yang mudah ditebak
  4. Kesalahan 3: token berumur panjang tanpa cara mencabut
  5. Kesalahan 4: menaruh data sensitif di payload
  6. Kesalahan 5: tidak memeriksa exp, iss, dan aud
  7. Di mana sebaiknya token disimpan di browser?
  8. Ringkasan kesalahan dan perbaikannya
  9. Perlukah JWT untuk aplikasi kecil?
  10. Pertanyaan yang sering diajukan

JWT aman dipakai untuk login asalkan verifikasinya ketat, tetapi banyak celah justru muncul dari cara memakainya, bukan dari format JWT itu sendiri. Kesalahan yang paling sering: algoritma tidak dikunci, secret terlalu lemah, token hidup terlalu lama, dan isi payload dianggap rahasia padahal bisa dibaca siapa saja.

Kenapa ini penting? Token login adalah kunci masuk ke akun. Kalau token bisa dipalsukan atau dipakai ulang oleh orang lain, penyerang tidak perlu menebak password sama sekali. Daftar di bawah disusun dari panduan resmi RFC 8725 (JWT Best Current Practices) dan OWASP JSON Web Token Cheat Sheet.

Apa sebenarnya JWT itu?

JWT (JSON Web Token) adalah string berisi tiga bagian yang dipisah titik: header, payload, dan tanda tangan. Header menyebut algoritma, payload berisi klaim seperti ID pengguna dan waktu kedaluwarsa, lalu tanda tangan membuktikan bahwa isi token tidak diubah sejak diterbitkan server.

Yang sering terlupa: tanda tangan hanya menjamin keaslian, bukan kerahasiaan. Header dan payload hanya dikodekan base64url, jadi siapa pun yang memegang token bisa membacanya.

Kesalahan 1: menerima algoritma apa pun yang tertulis di header

Header JWT punya kolom alg. Kalau server memakai nilai itu begitu saja untuk memilih cara verifikasi, penyerang bisa mengganti algoritmanya. Dua bentuk yang terkenal:

  • alg: none, yaitu token tanpa tanda tangan yang tetap diterima oleh pustaka yang longgar.
  • Kebingungan algoritma, misalnya token yang seharusnya diverifikasi dengan RSA (kunci publik) diubah menjadi HMAC, lalu kunci publik dipakai sebagai secret.

Perbaikannya sederhana: tentukan daftar algoritma yang diterima secara eksplisit di kode verifikasi, misalnya hanya ES256 atau hanya RS256. OWASP menyarankan menuliskan algoritma ini secara tetap saat validasi. Pastikan juga pustaka yang kamu pakai menolak token tanpa tanda tangan. Pustaka modern umumnya sudah begitu secara bawaan, tetapi tetap perlu dicek.

Kesalahan 2: secret HMAC yang mudah ditebak

Untuk HS256, keamanan token sepenuhnya bergantung pada secret. Secret seperti "rahasia123", nama aplikasi, atau nilai contoh dari tutorial bisa ditebak dengan serangan kamus secara offline: penyerang cukup punya satu token, lalu mencoba jutaan kandidat di komputernya sendiri tanpa menyentuh servermu.

RFC 8725 menegaskan password yang bisa diingat manusia tidak boleh dipakai langsung sebagai kunci HMAC. OWASP merekomendasikan secret dari pembangkit acak kriptografis, panjangnya minimal sepanjang keluaran hash (256 bit untuk HS256), dan tidak dipakai ulang untuk keperluan lain. Simpan secret di variabel lingkungan atau secret manager, jangan di repositori. Risiko bocornya file konfigurasi dibahas di mencegah bocornya file .env dan API key.

Kesalahan 3: token berumur panjang tanpa cara mencabut

JWT bersifat stateless: server memeriksa tanda tangan tanpa bertanya ke database. Ini praktis, tetapi ada konsekuensinya. Token yang sudah terbit tetap sah sampai exp, walaupun pengguna sudah logout, ganti password, atau akunnya diblokir.

Kesalahan umum adalah membuat token login berlaku berminggu-minggu supaya pengguna tidak perlu login ulang. Kalau token itu dicuri, penyerang menikmati waktu yang sama panjangnya. Pola yang lebih aman:

  • Access token berumur pendek.
  • Refresh token terpisah yang disimpan dan bisa dicabut di server.
  • Daftar pencabutan (denylist) bila memang perlu memutus sesi seketika. OWASP menyarankan denylist berbasis klaim jti dan iss, bukan string token mentah.

Begitu ada denylist, sebagian sifat stateless hilang. Itu harga yang wajar untuk aplikasi yang butuh tombol "keluar dari semua perangkat".

Kesalahan 4: menaruh data sensitif di payload

Karena payload bisa dibaca siapa saja, jangan isi dengan NIK, nomor telepon, alamat, saldo, atau peran internal yang tidak perlu diketahui klien. Token juga mudah tercecer: tersimpan di log, riwayat browser, atau header referrer.

Isi payload secukupnya, cukup ID pengguna dan klaim yang memang dibutuhkan untuk otorisasi. Data lain diambil server dari database saat diperlukan.

Kesalahan 5: tidak memeriksa exp, iss, dan aud

Memverifikasi tanda tangan saja belum cukup. Token yang tanda tangannya sah bisa saja sudah kedaluwarsa, diterbitkan oleh layanan lain, atau ditujukan untuk aplikasi lain. RFC 8725 meminta penerima memvalidasi penerbit (iss) dan, bila satu penerbit melayani beberapa aplikasi, mewajibkan klaim audiens (aud) yang cocok. OWASP juga mengingatkan untuk memeriksa exp dan nbf.

Kasus yang sering terjadi di bisnis yang punya beberapa aplikasi: satu server login menerbitkan token untuk aplikasi kasir dan aplikasi admin. Kalau aplikasi admin tidak memeriksa aud, token dari aplikasi kasir bisa ikut diterima.

Di mana sebaiknya token disimpan di browser?

Ini topik yang sering diperdebatkan. Token di localStorage bisa dibaca oleh JavaScript apa pun di halaman, sehingga satu celah XSS cukup untuk mencurinya. Cookie dengan atribut HttpOnly, Secure, dan SameSite tidak bisa dibaca JavaScript, tetapi membawa risiko CSRF yang perlu ditangani terpisah. Penjelasan soal CSRF ada di apa itu CSRF dan kenapa formulir butuh token.

Untuk aplikasi web biasa yang satu domain dengan API-nya, banyak tim memilih cookie HttpOnly. Untuk aplikasi mobile, gunakan penyimpanan aman bawaan sistem operasi (Keychain di iOS, Keystore di Android), bukan file teks biasa.

Ringkasan kesalahan dan perbaikannya

KesalahanAkibatPerbaikan
Algoritma diambil dari headerToken palsu bisa lolos (alg: none, kebingungan algoritma)Kunci daftar algoritma di kode verifikasi
Secret HMAC lemahSecret ditebak offline, token bisa dipalsukanSecret acak minimal 256 bit untuk HS256, simpan di luar repositori
Token berumur panjangToken curian bisa dipakai lamaAccess token pendek, refresh token yang bisa dicabut
Data sensitif di payloadData pribadi terbaca dari tokenIsi klaim seminimal mungkin
Klaim tidak divalidasiToken kedaluwarsa atau milik aplikasi lain diterimaPeriksa exp, nbf, iss, dan aud
Token di localStorageDicuri lewat XSSCookie HttpOnly + perlindungan CSRF, atau penyimpanan aman di mobile

Perlukah JWT untuk aplikasi kecil?

Tidak selalu. Untuk aplikasi web tunggal dengan satu server, sesi berbasis cookie biasa (ID sesi acak yang dicocokkan ke data di server) sering lebih sederhana dan lebih mudah dicabut. JWT lebih berguna ketika token perlu diverifikasi oleh beberapa layanan berbeda tanpa semuanya bertanya ke satu database, misalnya API untuk aplikasi mobile dan beberapa layanan internal.

Apa pun pilihannya, risiko pencurian sesi tetap ada. Cara penyerang mengambil alih sesi dan pencegahannya dibahas di apa itu session hijacking, sedangkan gambaran celah aplikasi web yang lebih luas ada di OWASP Top 10 untuk pemilik website.

Pertanyaan yang sering diajukan

Apakah JWT terenkripsi?

JWT yang umum dipakai (JWS) hanya ditandatangani, bukan dienkripsi. Isinya bisa dibaca siapa saja yang memegang token. Kalau isi token memang harus dirahasiakan, ada format JWE, tetapi untuk login biasanya lebih sederhana tidak menaruh data rahasia di token sama sekali.

Lebih aman HS256 atau RS256?

Keduanya aman bila dipakai dengan benar. HS256 memakai satu secret bersama, cocok bila penerbit dan pemeriksa token adalah server yang sama. RS256 atau ES256 memakai pasangan kunci, cocok bila banyak layanan perlu memverifikasi token tanpa ikut memegang kunci penandatangan.

Bagaimana cara logout kalau JWT tidak bisa dihapus dari server?

Hapus token di sisi klien, cabut refresh token di server, dan bila perlu masukkan ID token (jti) ke daftar pencabutan sampai waktu kedaluwarsanya lewat. Masa berlaku access token yang pendek membuat jendela risikonya kecil.

Sumber & referensi

Baca juga