cover

JWT Insight: Payloads, Secret Key Algoritma, dan Library

6 Minutes

JSON Web Token atau JWT (dibaca jot) adalah Token yang digunakan untuk melakukan proses claim dari 2 service yang berbeda (biasanya backend dan frontend). JWT memiliki standard RFC 7519. Berdasarkan sejarahnya JWT memiliki kelebihan yaitu ringkas (compact) dibandingkan pendahulunya SAML (Security Assertion Markup Language).

SAML dibuat tahun 2003
Sedangkan JWT pertama di publish tahun 2010

Membandingkan JWT dan SAML

Saat ini hampir semua website ataupun service yang menggunakan token ini dibandingkan harus menggunakan teknik lama tahun 1993 Basic Access Authentication yang mengharuskan mengirim username dan password (tanpa enkripsi atau hash) setiap pengiriman paket.

JWT memiliki beberapa komponen, yaitu Header, Payload, dan Signature. Header biasanya berisi algoritma yang digunakan dan type JWT (JWT, JWE). Payload adalah data token, sedangkan Signature adalah data untuk menandai siapa yang membuat token ini.

Header dan Payload

Membuat payload yang lengkap akan memudahkan validasi, dan debugging. Semakin lengkap dan validasi yang lengkap akan membuat aplikasi jadi lebih aman dari serangan hacker yang mencoba manipulasi JWT.

Kita akan bahas bagaimana validasi semua JWT pada section berikutnya.

Payload JWT berisi data JSON yang cukup simpel. Pada dasarnya bisa di isi apa saja, biasa disebut jwt claim.

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

Pertanyaannya adalah Claim apa saja yang perlu dibuat ? Berdasarkan standard RFC 7519 halaman 9, ada beberapa claim yang sudah di daftarkan dan semuanya bersifat opsional.

Untuk meracik Payload, pastikan setiap data di isi dengan tujuannya masing-masing, disarankan untuk mengikuti standard website atau service perusahaan agar mudah validasi.

  1. iss (Issuer) adalah penerbit JWT, biasanya URL backend

  2. sub (Subject) adalah subject user id yang unik, biasanya user id yang tersimpan di server

  3. aud (Audience) adalah identitas penerima (Recipents), biasanya URL dari frontend yang meminta JWT.

  4. exp (Expiration Time) adalah tangga kadaluarsa dalam bentuk milisecond

  5. nbf (Not Before) sebelum tanggal ini, JWT tidak valid.

  6. iat (Issued At) adalah tanggal JWT diterbitkan.

  7. jti (JWT ID) Tanda unik dari JWT. Berupa id unik yang berbeda dengan user id.

Claim ini sudah cukup lengkap menjelaskan tentang peran token, seperti :

  • Siapa yang membuat token ? terjawab dari iss

  • Siapa yang meminta dibuatkan token ? terjawab dari aud, ini akan berguna jika ada lebih dari 1 service/tipe seperti Client mobile dan web, aplikasi production user dan testing user,

  • Untuk siapa token ini ? terjawab dari sub berisi identitas user.

Selain claim diatas, anda bisa menambahkan claim lainnya seperti username, email, fullname. Tidak perlu semua data, hanya beberapa data saja.

Secret Key Algoritma

JWT secara default memiliki secret key. Ini digunakan saat menerbitkan JWT, hanya yang memiliki secret key dapat menerbitkan JWT.

Terdapat 2 tipe secret key yaitu asymmetric dan symmetric.

Symmetric menggunakan secret key yang sama untuk penerbitan dan validasi, sedangkan asymmetric menggunakan secret key untuk penerbitan dan gunakan public key untuk validasi.

Disarankan menggunakan Asymmetric secret code karena sudah banyak secret code symmetric yang tersebar di internet, seperti dijelaskan artikel ini ada 340 secret key yang tidak sengaja tersebar di publik repository kode.

Saya juga menulis tentang bagaimana menggunakan GPG Enkripsi yang memiliki asymmetric keys pada artikel GPG encryption snippet.

Symmetric Secret key (HS256)

JWT Algoritma HS256 menggunakan symmetric secret code. Berdasarkan buku JWT untuk penerbitan JWT cukup menggunakan 1 secret kode

const secret = 'my-secret';
const signed = jwt.sign(payload, secret, {
algorithm: 'HS256',
expiresIn: '5s' // if ommited, the token will not expire
});

dan untuk validasi

const secret = 'my-secret';

const decoded = jwt.verify(signed, secret, {
// Never forget to make this explicit to prevent
// signature stripping attacks
algorithms: ['HS256'],
});

Algorithma yang menggunakan symmetric secret key adalah yang menggunakan prefix HS.

Algoritma penerbitan (signing) ini cocok jika penggunaan Token kamu yakin siapa yang akan memegang secret key untuk validasi.

Tapi jika kamu tidak yakin mereka memegang secret key, gunakan RS256 Asymmetric secret key

Asymmetric Secret Key (RS256)

RS256 (RSA algorithm) menggunakan 2 key yaitu

  1. Private Key

  2. Public Key

Private key digunakan untuk menerbitkan (signing) JWT, ini hanya kamu yang pegang. Jangan di sebar luaskan atau hacker akan membuat JWT baru untuk membuat token baru.

Sedangkan Public key digunakan untuk verifikasi token, tidak bisa modifikasi Token JWT.

Ini sangat berguna jika kamu memiliki service lain yang diluar kendali mu, seperti aplikasi client yang memerlukan validasi dari token yang kamu terbitkan.

Juga ini lebih aman dibanding HS256 karena ada 2 kunci dan tidak mudah di bruteforce oleh hacker.

Cara Membuat asymmetric key bisa menggunakan OpenSSL

# Generate a private key
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
# Derive the public key from the private key
openssl rsa -pubout -in private_key.pem -out public_key.pem

Script diatas akan membuat file private_key.pem dan public_key.pem. Gunakan private_key.pem untuk membuat Token

const privateRsaKey = `<YOUR-PRIVATE-RSA-KEY>`;
const signed = jwt.sign(payload, privateRsaKey, {
algorithm: 'RS256',
expiresIn: '5s'
})

dan verifikasi menggunakan public_key.pem

const publicRsaKey = `<YOUR-PUBLIC-RSA-KEY>`;
const decoded = jwt.verify(signed, publicRsaKey, {
39
// Never forget to make this explicit to prevent
// signature stripping attacks.
algorithms: ['RS256'],
});

Kamu bisa menyebarkan public_key.pem kepada service lain, dan mereka bisa validasi bahwa token yang dibuat benar-benar dari service kamu.

Asymmetric Secret Key (ES256)

Selain HS256, kamu bisa gunakan ES256 (ECDSA algorithms), ECDSA tidak sepopuler RSA yang sudah banyak digunakan dalam TLS, sedangkan ECDSA memiliki keamanan lebih bagus mengikuti perkembangan cracking saat ini. Selain itu, ECDSA memiliki kunci yang lebih pendek dibanding RSA.

# Generate a private key (prime256v1 is the name of the parameters used
# to generate the key, this is the same as P-256 in the JWA spec).
openssl ecparam -name prime256v1 -genkey -noout -out ecdsa_private_key.pem
# Derive the public key from the private key
openssl ec -in ecdsa_private_key.pem -pubout -out ecdsa_public_key.pem

Script diatas akan membuat file ecdsa_private_key.pem dan ecdsa_public_key.pem.

Kamu bisa gunakan secret key ECDSA menggunakan algoritma ES256 seperti menggunakan RS256.

// You can get this from private_key.pem above.
const privateEcdsaKey = `<YOUR-PRIVATE-ECDSA-KEY>`;
const signed = jwt.sign(payload, privateEcdsaKey, {
algorithm: 'ES256',
expiresIn: '5s'
});

// You can get this from public_key.pem above.
const publicEcdsaKey = `<YOUR-PUBLIC-ECDSA-KEY>`;
const decoded = jwt.verify(signed, publicEcdsaKey, {
// Never forget to make this explicit to prevent
// signature stripping attacks.
algorithms: ['ES256'],
})

Validasi Token JWT

Saat validasi harus validasi algorithm yang digunakan dan semua claim harus diperiksa juga.

Kamu harus mengira semua token yang masuk pada sistem kamu itu tidak valid, walaupun secara kunci sudah valid.

Pencegahan sedetail mungkin untuk meningkatkan keamanan aplikasi dari JWT yang dimodifikasi atau token yang digunakan tidak tepat sesuai requirement bisnis. Pertanyaan-pertanyaan seperti ini harus di ajukan saat verifikasi token JWT

  • Apakah algoritma sama dengan algoritma penerbit ?

  • Apakah iss sudah benar dari penerbit ?

  • Apakah aud berasal dari audience yang dikenal ?

  • Apakah sub tersedia di database ?

  • Apakah jti sudah benar ?

Semua pertanyaan ini menjadi pelindung sistem anda dari serangan hacker. JWT.io dan Auth0 menjabarkan lebih rinci mengenai keamanan hingga standard dalam pembuatan library JSON web token.

Library

Ada berbagai library jsonwebtoken berdasarkan teknologi yang digunakan seperti :

Auth0 membuat library jsonwebtoken dan di public di npm. silahkan periksa di https://www.npmjs.com/package/jsonwebtoken

Golang tersedia library JWT di repository berikut https://github.com/golang-jwt/jwt

Rust juga tersedia library JWT https://docs.rs/jwt/latest/jwt/

Penutup

JSON web token adalah token stateless yang memiliki desain compact, URL friendly, dan berbagai opsi algoritma keamanan penerbitan Token JWT. Pemilihan algoritma sesuai kebutuhan dan validasi yang komplit akan membuat proses pertukaran data menjadi aman.


Referensi :

  1. Peyrott, Sebastián E. The JWT Handbook Version 0.14.1 (2016-2018), Auth0 Inc.
comments powered by Disqus