Secure Storage di Browser — Security

Penyimpanan Data di Browser Browser menyediakan beberapa mekanisme penyimpanan data. Masing-masing memiliki karakteristik keamanan yang berbeda, dan memilih…

Browser punya tiga tempat utama untuk menyimpan data: localStorage, sessionStorage, dan cookie. Bedanya ada di tiga hal: siapa yang bisa membacanya, kapan datanya hilang, dan apakah datanya ikut terkirim ke server. Untuk keamanan, pertanyaan terpentingnya: kalau ada script jahat di halamanmu (XSS), apa yang bisa dia baca? Bayangin kantor dengan tiga tempat menaruh kunci: laci meja yang gak dikunci, papan tulis yang dihapus tiap kali ruangan dikosongkan, dan brankas yang cuma bisa dibuka satpam. Penyusup yang masuk ruangan bisa membuka laci dan membaca papan tulis, tapi gak bisa membuka brankas. Lacinya localStorage, papan tulisnya sessionStorage, brankasnya cookie HttpOnly, dan satpamnya browser.

🧪 Tebakan cepat: token login disimpan di cookie dengan Secure dan SameSite=Strict, tapi tanpa HttpOnly. Script XSS di halamanmu bisa membacanya lewat document.cookie atau gak? Jawabannya ada di bagian "Cookie: cuma HttpOnly yang menyembunyikan dari script".

Tiga tempat, tiga sifat

localStorage sessionStorage Cookie biasa Cookie HttpOnly
Dibaca JavaScript halaman bisa bisa bisa, lewat document.cookie gak bisa
Ikut terkirim ke server gak gak ya, otomatis ya, otomatis
Hilang saat dihapus kode atau user tab ditutup kedaluwarsa kedaluwarsa
Kapasitas sekitar 5 MB per origin sekitar 5 MB per origin sekitar 4 KB per cookie sekitar 4 KB per cookie
localStorage.setItem("theme", "dark");
localStorage.getItem("theme"); // "dark", besok pun masih ada

sessionStorage.setItem("draft", "Halo, pesanan saya...");
// tutup tab: draft hilang

document.cookie; // "theme=dark" (cookie HttpOnly gak pernah muncul di sini)

Apa yang dibaca script XSS

Di Lab, Budi login di https://myapp.com, dan server mengembalikan JWT eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjQyfQ.c2lnbmF0dXJl. Aplikasinya menyimpan token itu di localStorage. Lalu ada komentar berisi script sisipan yang lolos ke halaman. Script itu jalan dengan hak yang sama dengan kodemu sendiri, jadi dia tinggal bertanya:

> localStorage.getItem("token")
'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjQyfQ.c2lnbmF0dXJl'
> document.cookie
'theme=dark'

Satu baris lagi, dan token itu terkirim ke server penyerang. Dengan token itu, penyerang bisa login sebagai Budi dari komputernya sendiri sampai token-nya kedaluwarsa. Karena itu JWT gak boleh disimpan di localStorage: tempat itu terbuka untuk semua JavaScript di halaman, termasuk script XSS. sessionStorage sama terbukanya, bedanya cuma lebih cepat hilang.

Cookie: cuma HttpOnly yang menyembunyikan dari script

Tempat paling aman untuk token login adalah cookie HttpOnly. Server yang memasangnya lewat header response:

Set-Cookie: token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjQyfQ.c2lnbmF0dXJl; Max-Age=7200; Path=/; HttpOnly; Secure; SameSite=Lax

Jadi cookie dengan Secure dan SameSite=Strict tapi tanpa HttpOnly tetap terbaca lewat document.cookie. Itu jawaban tebakannya.

Kodemu juga gak perlu menyentuh token-nya. Browser menempelkan cookie sendiri di setiap request ke myapp.com:

fetch("/api/orders", { credentials: "include" });

Satu hal lagi: cookie HttpOnly cuma bisa dibuat server. Kalau JavaScript menulis document.cookie = "token=abc; HttpOnly", browser mengabaikan cookie itu sepenuhnya.

Yang gak dicegah HttpOnly

HttpOnly mencegah token dicuri, bukan dipakai. Selama halaman yang kena XSS masih terbuka, script sisipan bisa memanggil fetch("/api/orders"), dan browser tetap menempelkan cookie-nya. Bedanya besar: penyerang gak bisa membawa token itu pulang dan memakainya dari tempat lain setelah Budi menutup tab.

Jadi HttpOnly mengurangi kerusakan, tapi obat utamanya tetap mencegah XSS: escaping output dan CSP, yang sudah kamu pelajari.

Simpan di mana?

Saat logout, bersihkan juga: hapus item di storage dengan removeItem, dan server mengirim ulang cookie-nya dengan Max-Age=0 supaya browser membuangnya.

💡 Bagaimana kalau token di localStorage dienkripsi?

Kedengarannya aman, tapi gak menolong melawan XSS. Untuk mendekripsi token, kodemu butuh kuncinya, dan kunci itu juga ada di halaman: di variabel, di storage, atau sebagai CryptoKey di IndexedDB. Script sisipan jalan dengan hak yang sama dengan kodemu, jadi dia bisa memakai kunci yang sama untuk mendekripsi, atau langsung memakai token-nya. Enkripsi di browser cuma menolong kalau seseorang membaca file browser di disk, bukan saat XSS.

⚠️ Jebakan yang sering ketemu

TL;DR: localStorage bertahan walau browser ditutup, sessionStorage hilang saat tab ditutup, dan keduanya bisa dibaca semua JavaScript di halaman, termasuk script XSS. Karena itu JWT atau token login gak boleh disimpan di sana: rentan XSS, penyerang tinggal menyalinnya. Tempat paling aman untuk token adalah cookie HttpOnly dengan Secure dan SameSite, yang dipasang server lewat Set-Cookie. HttpOnly satu-satunya flag yang menyembunyikan cookie dari document.cookie; Secure dan SameSite gak. HttpOnly mencegah token dicuri, bukan dipakai selama halaman yang kena XSS terbuka, jadi tetap cegah XSS-nya. Simpan preferensi di localStorage, draft di sessionStorage, dan data sensitif jangan di browser.

Yang akan kamu pelajari