Mengelola siklus hidup token di Keycloak: memahami peran refresh token, mekanisme rotasi dan offline access, konfigurasi masa berlaku token dan sesi, serta langkah-langkah keamanan untuk mendeteksi pencurian token.

Di episode 6 kalian memakai client credentials untuk mesin-ke-mesin — client cukup meminta token baru saat yang lama kedaluwarsa. Episode 7 ini berbeda: untuk user, memaksa login ulang setiap beberapa menit jelas tidak masuk akal. Di sinilah refresh token masuk — semacam kartu isi ulang yang memungkinkan access token baru didapat tanpa user mengetik password lagi.
Ada dua token yang beredar dalam sesi login user:
Pembagian peran ini mengurangi risiko: kalau access token bocor, jendela bahaya hanya selama masa berlakunya yang pendek. Kalau refresh token bocor, itulah masalah besar — karena bisa dipakai untuk membuat access token baru berulang kali.
| Aspek | Access Token | Refresh Token |
|---|---|---|
| Umur | Pendek, hitungan menit | Jauh lebih panjang |
| Isi | Claims dan roles | Pengenal sesi |
| Pemakaian | Dikirim ke API tujuan | Hanya ke token endpoint |
| Validasi | Resource server | Keycloak via token endpoint |
| Jika dicuri | Bahaya dalam masa berlaku | Sangat berbahaya, wajib dirotasi |
Ingat satu aturan emas: refresh token tidak pernah meninggalkan aplikasi. Dia tinggal di client, tidak ikut dalam request API apa pun.
Saat access token mendekati kedaluwarsa, aplikasi menukar refresh token di token endpoint:
curl -X POST "https://kc.example.com/realms/my-realm/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=my-app" \
-d "client_secret=4f9a2c8d..." \
-d "refresh_token=eyJhbGciOi..."Respons berisi access token baru, dan dengan rotasi aktif, refresh token baru juga:
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "eyJhbGciOiJSUzI1NiIs...",
"expires_in": 300,
"refresh_expires_in": 1800,
"token_type": "Bearer"
}grant_type=refresh_token menandai alur ini. Perhatikan refresh_expires_in — batas umur refresh token itu sendiri. Selama nilai ini belum nol, pertukaran berikutnya masih dimungkinkan.
Sejak Keycloak versi terbaru, rotasi refresh token aktif secara default: setiap kali kalian menukar refresh token, Keycloak mengeluarkan refresh token baru dan membatalkan yang lama. Token lama yang sama masih diterima dalam jendela singkat untuk menoleransi balapan request, tetapi di luar jendela itu, pemakaian token lama dianggap indikasi pencurian.
Inilah pertahanan utama terhadap skenario token dicuri: pencuri dan korban berebut memakai token yang sama, dan Keycloak bisa mendeteksi penggunaannya yang berulang. Jangan menonaktifkan rotasi tanpa alasan yang sangat kuat.
Untuk layanan yang tidak bisa memverifikasi signature JWT sendiri, Keycloak menyediakan introspection — meminta Keycloak menilai status sebuah token:
curl -s -X POST "https://kc.example.com/realms/my-realm/protocol/openid-connect/token/introspect" \
-H "Authorization: Basic base64(client_id:client_secret)" \
-d "token=eyJhbGciOi..."Respons active: true berarti token masih valid; active: false berarti sudah kedaluwarsa atau dicabut. Untuk mencabut token secara eksplisit — misalnya user logout atau refresh token dicurigai — pakai endpoint revoke:
curl -X POST "https://kc.example.com/realms/my-realm/protocol/openid-connect/revoke" \
-d "client_id=my-app" \
-d "client_secret=4f9a2c8d..." \
-d "token=eyJhbGciOi..."Important
Ingat aturan simpel: access token tidak bisa dicabut langsung. Karena berbentuk JWT stateless, mencabutnya berarti menunggu kedaluwarsa atau memaksa Keycloak memutar kunci. Yang bisa dicabut cepat adalah refresh token dan sesi user. Karena itu jaga refresh token sebagai aset paling sensitif dalam alur.
Semua angka ini diatur di Realm settings pada tab Tokens dan Sessions:
Tiga nilai inilah yang menentukan siklus hidup nyata token: meskipun refresh token terlihat awet, dia mati begitu sesi SSO-nya mati. Sesuaikan dengan kebutuhan — aplikasi internal yang santai boleh panjang, aplikasi keuangan sebaiknya pendek.
Untuk kasus yang butuh token hidup lebih lama — misalnya aplikasi mobile yang dibuka sebulan sekali — ada dua fitur:
offline_access, dan Keycloak mengeluarkan offline refresh token yang valid bahkan setelah sesi SSO user kedaluwarsa. Umurnya diatur oleh Offline Session Idle dan Offline Session Max.Bedanya: remember me tetap terikat pada sesi user, sedangkan offline access hidup mandiri. Pilih dengan sadar — keduanya memperpanjang eksposur kredensial.
Beberapa lapis pertahanan untuk token:
Tambahan praktis: token caching di sisi resource server. Jangan validasi ulang signature di setiap request bila tidak perlu — cache hasil validasi sampai exp, dengan pengecualian untuk token yang dicabut aktif.
Episode 7 mengupas refresh token: perannya memperpanjang akses tanpa login ulang, alur pertukarannya, rotasi dan deteksi pemakaian ulang, introspection dan revoke, konfigurasi lifespan di realm, offline access dan remember me, serta strategi keamanan token.
Inti yang harus dibawa pulang:
Di episode 8 berikutnya kalian akan mempelajari scopes dan consent — mekanisme yang menentukan data apa saja yang boleh diambil aplikasi dari akun user, dan bagaimana Keycloak menampilkan pilihan itu kepada user lewat layar persetujuan.