Perkembangan aplikasi web modern berbasis Single Page Application (SPA) seperti React, Vue, dan Next.js di Indonesia semakin pesat, seiring transformasi digital di sektor keuangan, e-commerce, dan layanan publik. Sebagian besar aplikasi tersebut mengandalkan autentikasi berbasis JSON Web Token (JWT) untuk mengamankan interaksi pengguna. Setelah proses login berhasil, server biasanya mengeluarkan dua jenis token: access token untuk mengautentikasi setiap permintaan dan refresh token untuk memperbarui access token tanpa memaksa pengguna login ulang. Pertanyaan krusial bagi pengembang frontend adalah di mana dan bagaimana menyimpan token tersebut agar tetap aman namun tetap memberikan pengalaman pengguna yang mulus. Panduan ini menyoroti arsitektur refresh token, risiko penyimpanan, serta implementasi praktis di sisi klien.
Access token dirancang berumur pendek, misalnya lima hingga lima belas menit, dan dikirimkan pada setiap request melalui header Authorization: Bearer. Jika token ini dicuri, penyerang hanya memiliki waktu terbatas untuk mengeksploitasinya. Sebaliknya, refresh token berumur lebih panjang dan tugasnya sangat spesifik: menerbitkan access token baru tanpa meminta kredensial pengguna lagi. Selama refresh token valid, pengguna dapat menutup tab browser dan kembali beberapa jam atau hari kemudian tanpa perlu login ulang. Perbedaan mendasar ini menuntut strategi penyimpanan yang berbeda pula.
Tanpa adanya refresh token, pengembang dihadapkan pada pilihan buruk: membuat access token berumur pendek sehingga pengguna sering diminta login, yang merusak pengalaman pengguna; atau membuatnya berumur panjang sehingga jika bocor, penyerang mendapat akses lama. Pemisahan token menjadi dua jenis menyelesaikan dilema tersebut: access token pendek untuk risiko rendah, refresh token panjang untuk kenyamanan. Pendekatan ini sangat relevan bagi perusahaan teknologi di Indonesia yang wajib mematuhi regulasi perlindungan data sambil menjaga retensi pengguna.
Alur autentikasi lengkap dengan refresh token dimulai dari login, di mana server mengembalikan access token dan menetapkan refresh token sebagai cookie HttpOnly serta Secure. Pada request normal, frontend membaca access token dari memori dan menyertakannya di header. Ketika access token kedaluwarsa, server merespons 401 Unauthorized, lalu frontend memanggil endpoint refresh; refresh token otomatis terkirim via cookie. Server memvalidasi dan mengeluarkan pasangan token baru, sering kali dengan rotasi token. Proses logout akan membatalkan refresh token dan menghapus cookie.
Salah satu kesalahan umum yang masih ditemui dalam banyak tutorial adalah menyimpan refresh token di localStorage. Praktik ini sangat berbahaya karena localStorage dapat dibaca oleh JavaScript secara bebas. Jika terjadi kerentanan XSS (Cross-Site Scripting), penyerang dapat mencuri token tersebut dan mengirimkannya ke server jahat. Dengan refresh token yang dicuri, penyerang dapat terus menerus mencetak access token baru dari lokasi mana pun. Oleh karena itu, hindari penyimpanan refresh token di localStorage maupun sessionStorage.
Praktik terbaik yang direkomendasikan untuk SPA adalah menyimpan access token di memori aplikasi, misalnya pada variabel atau state manager seperti Redux atau Zustand. Token ini memang hilang saat reload penuh, namun refresh token akan mengeluarkan yang baru. Sementara itu, refresh token harus disimpan sebagai cookie HttpOnly di domain backend. Flag HttpOnly membuatnya tidak dapat diakses JavaScript sehingga kebal terhadap XSS. Flag Secure memastikan transmisi hanya via HTTPS, dan SameSite=Strict atau Lax meminimalisir risiko CSRF. Pengaturan Path=/auth/refresh membatasi pengiriman cookie hanya ke endpoint tersebut.
Rotasi token (token rotation) merupakan komponen keamanan lanjutan yang sangat penting. Setiap kali refresh token digunakan untuk memperoleh access token baru, server sekaligus menerbitkan refresh token baru dan membatalkan yang lama. Manfaatnya, token lama yang perhaps dicuri akan mati setelah sesi berikutnya. Jika ada penggunaan bersamaan dari IP berbeda, sistem dapat mendeteksi anomali dan menutup sesi. Mekanisme ini memberikan lapisan pertahanan tambahan bagi aplikasi yang melayani jutaan pengguna, termasuk di pasar Indonesia.
Implementasi di sisi frontend dengan library Axios dapat mengillustrasikan konsep di atas. Access token disimpan dalam variabel memori melalui modul sederhana. Saat login, respons server menyimpan access token, sementara refresh token diatur oleh backend sebagai cookie. Interceptor request menambahkan header Authorization secara otomatis, sedangkan interceptor response menangani error 401 dengan memanggil endpoint refresh, lalu mencoba ulang request yang tertunda. Pola ini menjaga UX tetap halus tanpa mengorbankan keamanan.
Bagi industri teknologi Indonesia, adopsi arsitektur refresh token yang aman bukan sekadar tren teknis, melainkan kebutuhan strategis. Maraknya serangan siber terhadap layanan digital domestik menuntut pengembang untuk meninggalkan kebiasaan buruk penyimpanan token di penyimpanan klien yang mudah diakses. Standar seperti cookie HttpOnly dan rotasi token selaras dengan rancangan Undang-Undang Pelindungan Data Pribadi. Dengan menerapkan praktik ini, startup dan perusahaan dapat membangun kepercayaan pengguna sekaligus mengurangi potensi kebocoran data berskala besar.