(muncul dari utas ini karena ini benar-benar pertanyaannya sendiri dan tidak khusus untuk NodeJS dll)
Saya menerapkan server REST API dengan otentikasi, dan saya telah berhasil menerapkan penanganan token JWT sehingga pengguna dapat masuk melalui / login endpoint dengan nama pengguna / kata sandi, di mana token JWT dibuat dari rahasia server dan dikembalikan ke klien. Token kemudian diteruskan dari klien ke server di setiap permintaan API yang diautentikasi, di mana rahasia server digunakan untuk memverifikasi token.
Namun, saya mencoba untuk memahami praktik terbaik tentang bagaimana dan sejauh mana token harus divalidasi, untuk membuat sistem yang benar-benar aman. Persis apa yang harus dilibatkan dalam "memvalidasi" token? Apakah cukup bahwa tanda tangan dapat diverifikasi menggunakan rahasia server, atau haruskah saya juga memeriksa ulang token dan / atau muatan token terhadap beberapa data yang disimpan di server?
Sistem otentikasi berbasis token hanya akan seaman meneruskan nama pengguna / kata sandi di setiap permintaan asalkan sama atau lebih sulit untuk mendapatkan token daripada mendapatkan kata sandi pengguna. Namun, dalam contoh yang saya lihat, satu-satunya informasi yang diperlukan untuk menghasilkan token adalah nama pengguna dan rahasia sisi server. Bukankah ini berarti bahwa dengan asumsi selama satu menit bahwa pengguna yang jahat memperoleh pengetahuan tentang rahasia server, dia sekarang dapat menghasilkan token atas nama pengguna mana pun , sehingga memiliki akses tidak hanya untuk satu pengguna tertentu seperti halnya fakta jika kata sandi digunakan. diperoleh, tetapi sebenarnya untuk semua akun pengguna?
Ini membawa saya pada pertanyaan:
1) Apakah validasi token JWT harus dibatasi untuk memverifikasi tanda tangan token itu sendiri, mengandalkan integritas rahasia server saja, atau disertai dengan mekanisme validasi terpisah?
Dalam beberapa kasus saya telah melihat penggunaan gabungan dari token dan sesi server di mana setelah berhasil masuk melalui / login endpoint sesi dibuat. Permintaan API memvalidasi token, dan juga membandingkan data yang didekodekan yang ditemukan di token dengan beberapa data yang disimpan dalam sesi. Namun, menggunakan sesi berarti menggunakan cookie, dan dalam beberapa hal hal itu mengalahkan tujuan penggunaan pendekatan berbasis token. Ini juga dapat menyebabkan masalah bagi klien tertentu.
Dapat dibayangkan server menyimpan semua token yang saat ini digunakan di memcache atau yang serupa, untuk memastikan bahwa meskipun rahasia server dikompromikan sehingga penyerang dapat menghasilkan token "valid", hanya token persis yang dihasilkan melalui titik akhir / login akan diterima. Apakah ini masuk akal atau hanya berlebihan / berlebihan?
2) Jika verifikasi tanda tangan JWT adalah satu-satunya cara untuk memvalidasi token, yang berarti integritas rahasia server adalah titik puncaknya, bagaimana seharusnya rahasia server dikelola? Membaca dari variabel lingkungan dan dibuat (diacak?) Sekali per tumpukan yang diterapkan? Dibarui kembali atau dirotasi secara berkala (dan jika demikian, bagaimana menangani token valid yang ada yang dibuat sebelum rotasi tetapi perlu divalidasi setelah rotasi, mungkin cukup jika server menyimpan rahasia saat ini dan sebelumnya pada waktu tertentu) ? Sesuatu yang lain?
Mungkin saya hanya terlalu paranoid ketika menghadapi risiko rahasia server disusupi, yang tentu saja merupakan masalah yang lebih umum yang perlu ditangani dalam semua situasi kriptografi ...
RSAPrivateKey privateKey
??Jawaban:
Saya telah bermain dengan token untuk aplikasi saya juga. Meskipun saya bukan ahli dengan cara apa pun, saya dapat berbagi beberapa pengalaman dan pemikiran saya tentang masalah ini.
Inti dari JWT pada dasarnya adalah integritas. Ini menyediakan mekanisme untuk server Anda memverifikasi bahwa token yang diberikan kepadanya adalah asli dan disediakan oleh server Anda. Tanda tangan yang dihasilkan melalui rahasia Anda adalah yang menyediakan untuk ini. Jadi, ya, jika rahasia Anda bocor, orang tersebut dapat menghasilkan token yang menurut server Anda adalah miliknya sendiri. Sistem berbasis token masih akan lebih aman daripada sistem nama pengguna / kata sandi Anda hanya karena verifikasi tanda tangan. Dan dalam kasus ini, jika seseorang memiliki rahasia Anda, sistem Anda memiliki masalah keamanan lain yang harus dihadapi selain seseorang yang membuat token palsu (dan bahkan kemudian, hanya dengan mengubah rahasianya memastikan bahwa token yang dibuat dengan rahasia lama sekarang tidak valid).
Sedangkan untuk payload, tanda tangan hanya akan memberi tahu Anda bahwa token yang diberikan kepada Anda persis seperti saat server Anda mengirimkannya. memverifikasi bahwa konten payload valid atau sesuai untuk aplikasi Anda jelas terserah Anda.
Untuk pertanyaan Anda:
1.) Dalam pengalaman saya yang terbatas, lebih baik memverifikasi token Anda dengan sistem kedua. Memvalidasi tanda tangan berarti token dibuat dengan rahasia Anda. Menyimpan token yang dibuat dalam beberapa jenis DB (redis, memcache / sql / mongo, atau beberapa penyimpanan lainnya) adalah cara yang fantastis untuk memastikan bahwa Anda hanya menerima token yang telah dibuat oleh server Anda. Dalam skenario ini, meskipun rahasia Anda bocor, itu tidak terlalu menjadi masalah karena token yang dibuat tidak akan valid. Ini adalah pendekatan yang saya ambil dengan sistem saya - semua token yang dihasilkan disimpan dalam DB (redis) dan pada setiap permintaan, saya memverifikasi bahwa token ada di DB saya sebelum saya menerimanya. Dengan cara ini token dapat dicabut untuk alasan apa pun, seperti token yang entah bagaimana dilepaskan ke alam liar, logout pengguna, perubahan kata sandi, perubahan rahasia, dll.
2.) Ini adalah sesuatu yang tidak banyak saya alami dan masih saya teliti secara aktif karena saya bukan seorang profesional keamanan. Jika Anda menemukan sumber daya apa pun, silakan posting di sini! Saat ini, saya hanya menggunakan kunci pribadi yang saya muat dari disk, tetapi jelas itu jauh dari solusi terbaik atau paling aman.
sumber
Berikut beberapa hal yang perlu dipertimbangkan saat menerapkan JWT di aplikasi Anda:
Jaga agar masa pakai JWT Anda relatif singkat, dan kelola seumur hidup di server. Jika tidak, dan nanti perlu informasi lebih lanjut di JWT Anda, Anda harus mendukung 2 versi, atau menunggu sampai JWT lama Anda kedaluwarsa sebelum Anda dapat menerapkan perubahan Anda. Anda dapat dengan mudah mengelolanya di server jika Anda hanya melihat
iat
bidang di jwt, dan mengabaikanexp
bidang tersebut.Pertimbangkan untuk menyertakan url permintaan di JWT Anda. Misalnya, jika Anda ingin JWT Anda digunakan di titik akhir
/my/test/path
, sertakan bidang seperti'url':'/my/test/path'
di JWT Anda, untuk memastikannya hanya digunakan di jalur ini. Jika tidak, Anda mungkin menemukan bahwa orang-orang mulai menggunakan JWT Anda di titik akhir lain, bahkan yang bukan tujuan pembuatannya. Anda juga dapat mempertimbangkan untuk menyertakan md5 (url) sebagai gantinya, karena memiliki url besar di JWT akan membuat JWT menjadi jauh lebih besar, dan mereka bisa menjadi cukup besar.Kedaluwarsa JWT harus dapat dikonfigurasi oleh setiap kasus penggunaan jika JWT sedang diterapkan di API. Misalnya, jika Anda memiliki 10 titik akhir untuk 10 kasus penggunaan berbeda untuk JWT, pastikan Anda dapat membuat setiap titik akhir menerima JWT yang kedaluwarsa pada waktu yang berbeda. Ini memungkinkan Anda untuk mengunci beberapa titik akhir lebih dari yang lain, jika misalnya, data yang disajikan oleh satu titik akhir sangat sensitif.
Alih-alih hanya mengakhiri JWT setelah waktu tertentu, pertimbangkan untuk menerapkan JWT yang mendukung keduanya:
Semua kegagalan autentikasi JWT seharusnya menghasilkan header respons "error" yang menyatakan mengapa autentikasi JWT gagal. misalnya "kedaluwarsa", "tidak ada penggunaan yang tersisa", "dicabut", dll. Hal ini membantu pelaksana mengetahui mengapa JWT mereka gagal.
Pertimbangkan untuk mengabaikan "header" JWT Anda karena JWT tersebut membocorkan informasi dan memberikan ukuran kontrol kepada peretas. Ini sebagian besar menyangkut
alg
bidang di header - abaikan ini dan anggap saja header adalah yang ingin Anda dukung, karena ini menghindari peretas yang mencoba menggunakanNone
algoritme, yang menghapus pemeriksaan keamanan tanda tangan.JWT harus menyertakan pengenal yang merinci aplikasi mana yang menghasilkan token. Misalnya jika JWT Anda dibuat oleh 2 klien berbeda, mychat, dan myclassifiedsapp, maka masing-masing harus menyertakan nama proyeknya atau sesuatu yang serupa di kolom "iss" di JWT, misalnya "iss": "mychat"
iat
(diterbitkan pada) alih-alihexp
(kedaluwarsa) di JWT Anda. Mengapa? Karenaiat
pada dasarnya berarti kapan JWT dibuat, ini memungkinkan Anda untuk menyesuaikan di server ketika JWT berakhir, berdasarkan tanggal pembuatan. Jika seseorang lewat dalamexp
20 tahun ke depan, JWT pada dasarnya hidup selamanya! Perhatikan bahwa Anda secara otomatis kedaluwarsa JWT jika merekaiat
ada di masa mendatang, tetapi memungkinkan untuk sedikit ruang gerak (misalnya 10 detik), jika waktu klien sedikit tidak sinkron dengan waktu server./mysite/userInfo?jwt=XXX
dan url ini akan disimpan dalam cache. Mereka keluar dan beberapa menit kemudian, pengguna biasa masuk ke aplikasi Anda. Mereka akan mendapatkan konten yang disimpan dalam cache - dengan info tentang pengguna super! Hal ini cenderung lebih jarang terjadi pada klien, dan lebih banyak pada server, terutama dalam kasus di mana Anda menggunakan CDN seperti Akamai, dan Anda membiarkan beberapa file hidup lebih lama. Ini dapat diperbaiki dengan memasukkan info pengguna yang relevan di url, dan memvalidasinya di server, bahkan untuk permintaan yang disimpan dalam cache, misalnya/mysite/userInfo?id=52&jwt=XXX
sumber
created_by
, sudah ada klaim untuk itu di JWT dan itu disebutiss
(penerbit).Saya tidak berpikir saya seorang ahli tetapi saya ingin berbagi beberapa pemikiran tentang Jwt.
1: Seperti yang dikatakan Akshay, lebih baik memiliki sistem kedua untuk memvalidasi token Anda.
a .: Cara saya menanganinya: Saya menyimpan hash yang dihasilkan ke dalam penyimpanan sesi dengan waktu kedaluwarsa. Untuk memvalidasi sebuah token, itu harus sudah diterbitkan oleh server.
b.:Setidaknya ada satu hal yang harus diperiksa metode tanda tangan yang digunakan. misal:
Beberapa perpustakaan yang memvalidasi JWT akan menerima yang ini tanpa memeriksa hash. Itu berarti bahwa tanpa mengetahui salt Anda yang digunakan untuk menandatangani token tersebut, seorang hacker dapat memberikan dirinya beberapa hak. Selalu pastikan ini tidak bisa terjadi. https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
c .: Menggunakan cookie dengan ID sesi tidak akan berguna untuk memvalidasi token Anda. Jika seseorang ingin membajak sesi pengguna lambda, dia hanya perlu menggunakan sniffer (misalnya: wireshark). Peretas ini akan memiliki kedua informasi pada saat yang bersamaan.
Cara saya menanganinya terkait dengan poin 1.a. : Saya memiliki rahasia yang dicampur dengan variabel acak. Rahasianya unik untuk setiap token.
Jika Anda menginginkan keamanan terbaik, Anda tidak boleh mengikuti praktik terbaik secara membabi buta. Cara terbaik adalah memahami apa yang Anda lakukan (menurut saya tidak masalah jika saya melihat pertanyaan Anda), lalu evaluasi keamanan yang Anda butuhkan. Dan jika Mossad ingin memiliki akses ke data rahasia Anda, mereka akan selalu menemukan caranya. (Saya suka posting blog ini: https://www.schneier.com/blog/archives/2015/08/mickens_on_secu.html )
sumber
Banyak jawaban bagus di sini. Saya akan mengintegrasikan beberapa jawaban yang menurut saya paling relevan dan menambahkan beberapa saran lagi.
1) Apakah validasi token JWT harus dibatasi untuk memverifikasi tanda tangan token itu sendiri, mengandalkan integritas rahasia server saja, atau disertai dengan mekanisme validasi terpisah?
Tidak, karena alasan yang tidak terkait dengan penyusupan rahasia token. Setiap kali pengguna masuk melalui nama pengguna dan kata sandi, server otorisasi harus menyimpan baik token yang dibuat, atau metadata tentang token yang dibuat. Pikirkan metadata ini sebagai catatan otorisasi. Pasangan pengguna dan aplikasi tertentu hanya boleh memiliki satu token atau otorisasi yang valid pada waktu tertentu. Metadata yang berguna adalah id pengguna yang terkait dengan token akses, id aplikasi, dan waktu ketika token akses diterbitkan (yang memungkinkan pencabutan token akses yang ada dan penerbitan token akses baru). Pada setiap permintaan API, validasi bahwa token berisi metadata yang sesuai. Anda perlu menyimpan informasi tentang kapan setiap token akses diterbitkan, sehingga pengguna dapat mencabut token akses yang ada jika kredensial akun mereka disusupi, dan masuk lagi dan mulai menggunakan token akses baru. Itu akan memperbarui database dengan waktu ketika token akses dikeluarkan (waktu otorisasi dibuat). Pada setiap permintaan API, periksa apakah waktu penerbitan token akses setelah waktu otorisasi dibuat.
Langkah-langkah keamanan lainnya termasuk tidak mencatat JWT dan memerlukan algoritme penandatanganan aman seperti SHA256.
2) Jika verifikasi tanda tangan JWT adalah satu-satunya cara untuk memvalidasi token, yang berarti integritas rahasia server adalah titik puncaknya, bagaimana seharusnya rahasia server dikelola?
Penyusupan rahasia server akan memungkinkan penyerang mengeluarkan token akses untuk pengguna mana pun, dan menyimpan data token akses pada langkah 1 tidak akan serta merta mencegah server menerima token akses tersebut. Misalnya, pengguna telah diberi token akses, dan kemudian, penyerang membuat token akses untuk pengguna tersebut. Waktu otorisasi token akses akan valid.
Seperti yang dikatakan Akshay Dhalwala, jika rahasia sisi server Anda dikompromikan, maka Anda memiliki masalah yang lebih besar untuk ditangani karena itu berarti penyerang telah menyusupi jaringan internal Anda, repositori kode sumber Anda, atau keduanya.
Namun, sistem untuk mengurangi kerusakan rahasia server yang disusupi dan menghindari penyimpanan rahasia dalam kode sumber melibatkan rotasi rahasia token menggunakan layanan koordinasi seperti https://zookeeper.apache.org. Gunakan tugas cron untuk membuat rahasia aplikasi setiap beberapa jam atau lebih (berapa lama token akses Anda valid), dan serahkan rahasia yang diperbarui ke Zookeeper. Di setiap server aplikasi yang perlu mengetahui rahasia token, konfigurasikan klien ZK yang diperbarui setiap kali nilai node ZK berubah. Simpan rahasia utama dan sekunder, dan setiap kali rahasia token diubah, setel rahasia token baru ke yang utama dan rahasia token lama ke sekunder. Dengan begitu, token valid yang ada akan tetap valid karena akan divalidasi dengan rahasia sekunder. Pada saat rahasia sekunder diganti dengan rahasia primer lama, semua token akses yang dikeluarkan dengan rahasia sekunder akan kedaluwarsa.
sumber
IETF memiliki RFC yang sedang berlangsung di Kelompok Kerja oAuth lihat: https://tools.ietf.org/id/draft-ietf-oauth-jwt-bcp-05.html
sumber