Penyimpanan atau cookie lokal? Menyimpan JWT dengan aman di klien

JWT (JSON Web Token) adalah standar berbasis JSON yang bagus untuk membuat token akses yang biasa digunakan untuk otentikasi dalam aplikasi klien / server. Saat menggunakan token ini, muncul pertanyaan tentang bagaimana menyimpannya dengan aman di front-end aplikasi. Masalah ini harus diselesaikan segera setelah token dibuat di server dan ditransfer ke sisi klien aplikasi. Materi, terjemahan yang kami terbitkan hari ini, dikhususkan untuk analisis pro dan kontra penggunaan penyimpanan lokal browser ( ) dan cookie untuk menyimpan JWT.







localStorage



Jenis token



  • Token akses biasanya JWT berumur pendek yang ditandatangani oleh server. Mereka disertakan dalam setiap permintaan HTTP yang dibuat klien ke server. Token digunakan untuk mengotorisasi permintaan.
  • Refresh token biasanya berupa token berumur panjang yang disimpan dalam database dan digunakan untuk mendapatkan token akses baru ketika token sebelumnya kedaluwarsa.


Di mana tepatnya token disimpan di klien?



Ada 2 cara umum untuk menyimpan token di klien: penyimpanan browser lokal dan cookie. Ada banyak perdebatan tentang metode mana yang lebih baik. Kebanyakan orang memilih cookie karena keamanannya yang lebih baik.



Mari bandingkan penyimpanan lokal dan cookie. Perbandingan kami terutama didasarkan pada materi ini dan komentarnya.



Penyimpanan lokal



▍Keuntungan



Keuntungan utama dari penyimpanan lokal adalah nyaman digunakan.



  • Bekerja dengan penyimpanan lokal sangat nyaman, JavaScript murni digunakan di sini. Jika aplikasi Anda tidak memiliki backend dan Anda mengandalkan API pihak ketiga, Anda mungkin tidak selalu dapat meminta API ini untuk menyetel cookie tertentu untuk situs Anda.
  • Menggunakan penyimpanan lokal, akan lebih mudah bekerja dengan API yang memerlukan penempatan token akses di header permintaan. Misalnya - sebagai berikut: Authorization Bearer ${access_token}.


▍Kekurangan



Kerugian utama dari penyimpanan lokal adalah kerentanannya terhadap serangan XSS.



  • Saat melakukan serangan XSS, penyerang dapat menjalankan kode JavaScript mereka di situs Anda. Ini berarti penyerang dapat memperoleh akses ke token akses yang disimpan di localStorage.
  • Sumber serangan XSS dapat berupa kode JavaScript pihak ketiga yang disertakan di situs Anda. Bisa jadi sesuatu seperti React, Vue, jQuery, script Google Analytics, dan sebagainya. Dalam kondisi modern, hampir tidak mungkin untuk mengembangkan situs yang tidak menyertakan pustaka pihak ketiga.


Kue



▍Keuntungan



Keuntungan utama cookie adalah tidak dapat diakses dari JavaScript. Akibatnya, mereka tidak rentan terhadap serangan XSS seperti penyimpanan lokal.



  • Jika Anda menggunakan bendera HttpOnlydan cookie aman, itu berarti JavaScript tidak dapat mengakses file-file ini. Artinya, meskipun penyerang dapat menjalankan kodenya di halaman Anda, dia tidak akan dapat membaca token akses dari cookie.
  • Cookie secara otomatis dikirim di setiap permintaan HTTP ke server.


▍Kekurangan



Bergantung pada keadaan tertentu, mungkin saja token dalam cookie tidak dapat disimpan.



  • Ukuran cookie dibatasi hingga 4 KB. Oleh karena itu, jika Anda menggunakan JWT besar, menyimpannya dalam cookie tidak akan berfungsi untuk Anda.
  • Ada beberapa skenario di mana Anda tidak dapat meneruskan cookie ke server API Anda. Mungkin juga beberapa API memerlukan penempatan token di header Authorization. Dalam kasus ini, Anda tidak akan dapat menyimpan token dalam cookie.


Serangan XSS



Penyimpanan lokal rentan terhadap serangan XSS karena sangat mudah untuk bekerja dengan menggunakan JavaScript. Oleh karena itu, penyerang dapat memperoleh akses ke token dan menggunakannya untuk keuntungan mereka. Namun, meskipun cookie HttpOnly tidak dapat dijangkau dari JavaScript, ini tidak berarti bahwa Anda dilindungi dari serangan XSS dengan menggunakan cookie untuk mencuri token akses.



Jika penyerang dapat menjalankan kode JS mereka di aplikasi Anda, ini berarti bahwa mereka dapat dengan mudah mengirim permintaan ke server Anda, dan token akan disertakan dalam permintaan ini secara otomatis. Skema kerja seperti itu sama sekali tidak nyaman bagi penyerang, karena dia tidak dapat membaca konten token. Tetapi penyerang jarang membutuhkan ini. Selain itu, dengan skema kerja ini, mungkin lebih menguntungkan bagi penyerang untuk menyerang server menggunakan komputer korban, daripada miliknya sendiri.



Cookie dan serangan CSRF



Serangan CSRF adalah serangan di mana pengguna dipaksa untuk membuat permintaan khusus. Misalnya, situs menerima permintaan untuk mengubah alamat email:



POST /email/change HTTP/1.1
Host: site.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
Cookie: session=abcdefghijklmnopqrstu

email=myemail.example.com


Dalam situasi seperti itu, penyerang dapat membuat formulir dengan bidang tersembunyi untuk memasukkan alamat email yang mengirimkan permintaan POST https://site.com/email/change. Dalam hal ini, cookie sesi akan secara otomatis disertakan dalam permintaan tersebut.



Namun, ancaman ini dapat dengan mudah dilindungi dengan menggunakan atribut SameSitedi header respons dan token anti-CSRF .



Subtotal



Meskipun cookie tidak sepenuhnya kebal terhadap serangan, cara terbaik untuk menyimpan token adalah, jika memungkinkan, memilihnya localStorage. Mengapa?



  • Baik penyimpanan lokal dan cookie rentan terhadap serangan XSS, tetapi akan lebih sulit bagi penyerang untuk menyerang jika cookie HttpOnly digunakan.
  • Cookies rentan terhadap serangan CSRF, tetapi risiko serangan tersebut dapat dikurangi dengan menggunakan atribut SameSitedan token anti-CSRF .


Cookie dapat digunakan bahkan saat Anda perlu menggunakan header Authorization: Beareratau saat JWT lebih besar dari 4KB. Ini juga konsisten dengan pedoman OWASP: “Jangan simpan ID sesi di penyimpanan lokal, karena data yang sesuai selalu tersedia dari JavaScript. Cookie dapat membantu mengurangi risiko dengan HttpOnly. "



Menggunakan cookie untuk menyimpan token OAuth 2.0



Mari kita daftar secara singkat cara menyimpan token:



  • Metode 1: Menyimpan token di penyimpanan lokal. Metode ini rentan terhadap serangan XSS.
  • Metode 2: Menyimpan token di cookie HttpOnly. Metode ini rentan terhadap serangan CSRF, tetapi risiko serangan tersebut dapat dikurangi. Opsi penyimpanan token ini sedikit lebih terlindungi dari serangan XSS daripada yang pertama.
  • Metode 3: Simpan token penyegaran di cookie HttpOnly dan akses token di memori. Cara menyimpan token ini lebih aman dalam hal serangan CSRF dan sedikit lebih terlindungi dari serangan XSS.


Di bawah ini kita akan melihat lebih dekat pada metode ketiga untuk menyimpan token, karena metode ketiga yang terdaftar, terlihat paling menarik.



Mengapa menyimpan token penyegaran dalam cookie HttpOnly lebih aman dalam hal serangan CSRF?



Penyerang dapat membuat formulir yang mengakses /refresh_token. Token akses baru dikembalikan sebagai tanggapan atas permintaan ini. Tetapi penyerang tidak dapat membaca respon jika dia menggunakan bentuk HTML. Untuk mencegah penyerang agar tidak berhasil menjalankan permintaan ambil atau AJAX dan membaca tanggapan, kebijakan CORS server otorisasi harus dikonfigurasi dengan benar, yaitu, agar server tidak menanggapi permintaan dari situs web yang tidak sah.



Bagaimana Anda menyiapkannya?



Langkah 1: Kembalikan token akses dan segarkan token saat mengautentikasi pengguna



Setelah pengguna mengautentikasi, server otentikasi kembali access_token(token akses) dan refresh_token(token penyegaran). Token akses akan dimasukkan ke dalam isi respons dan token penyegaran di cookie.



Inilah yang perlu Anda gunakan untuk menyiapkan cookie untuk menyimpan token penyegaran:



  • Bendera HttpOnly- untuk mencegah JavaScript membaca token.
  • Sebuah tanda secure=trueyang akan menyebabkan data dikirim hanya melalui HTTPS.
  • Bendera SameSite=strictharus digunakan sebisa mungkin untuk melindungi dari serangan CSRF. Pendekatan ini hanya dapat digunakan jika server otorisasi berada di situs yang sama dengan frontend sistem. Jika tidak demikian, server otorisasi harus menyetel header CORS di backend, atau menggunakan metode lain untuk memastikan bahwa permintaan dengan token penyegaran hanya dapat dibuat oleh situs web resmi.


Langkah 2: simpan token akses di memori



Menyimpan token akses dalam memori berarti token, dalam kode frontend, ditulis ke variabel. Ini, tentu saja, berarti bahwa token akan hilang jika pengguna menutup tab tempat situs tersebut dibuka atau memuat ulang halaman. Inilah mengapa kami memiliki token penyegaran.



Langkah 3: Dapatkan token akses baru menggunakan token penyegaran



Jika token akses ternyata hilang atau tidak valid, Anda perlu menghubungi titik akhir /refresh_token. Dalam kasus ini, token penyegaran, yang, pada langkah 1, disimpan dalam cookie, akan disertakan dalam permintaan. Anda kemudian akan menerima token akses baru yang dapat Anda gunakan untuk membuat permintaan API.



Semua ini berarti JWT bisa lebih besar dari 4KB, dan bisa ditempatkan di header Authorization.



Hasil



Apa yang telah kami bahas di sini seharusnya memberi Anda beberapa informasi dasar tentang menyimpan JWT di klien dan bagaimana membuat proyek Anda lebih aman.



Bagaimana Anda menyimpan JWT di klien?






All Articles