Ketika membangun aplikasi gaya SPA menggunakan kerangka kerja seperti Angular, Ember, React, dll. Apa yang orang yakini sebagai beberapa praktik terbaik untuk otentikasi dan manajemen sesi? Saya dapat memikirkan beberapa cara untuk mempertimbangkan mendekati masalah.
Perlakukan itu tidak berbeda dengan otentikasi dengan aplikasi web biasa dengan asumsi API dan UI memiliki domain asal yang sama.
Ini kemungkinan akan melibatkan memiliki cookie sesi, penyimpanan sesi sisi server dan mungkin beberapa titik akhir API sesi yang dapat dicapai UI web terautentikasi untuk mendapatkan informasi pengguna saat ini untuk membantu dengan personalisasi atau bahkan mungkin menentukan peran / kemampuan di sisi klien. Server masih akan memberlakukan aturan yang melindungi akses ke data tentu saja, UI hanya akan menggunakan informasi ini untuk menyesuaikan pengalaman.
Perlakukan seperti layaknya klien pihak ketiga yang menggunakan API publik dan autentikasi dengan semacam sistem token yang mirip dengan OAuth. Mekanisme token ini akan digunakan oleh UI klien untuk mengotentikasi setiap permintaan yang dibuat ke API server.
Saya tidak terlalu ahli di sini, tetapi # 1 tampaknya cukup untuk sebagian besar kasus, tetapi saya benar-benar ingin mendengar pendapat yang lebih berpengalaman.
sumber
Jawaban:
Pertanyaan ini telah ditanggapi, dalam bentuk yang sedikit berbeda, panjangnya, di sini:
Otentikasi tenang
Tapi ini mengatasinya dari sisi server. Mari kita lihat ini dari sisi klien. Namun, sebelum kita melakukan itu, ada pembuka penting:
Javascript Crypto Tidak Ada Harapan
Artikel Matasano tentang ini terkenal, tetapi pelajaran yang terkandung di dalamnya cukup penting:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
Untuk meringkas:
<script> function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
Dan untuk menambahkan akibat wajar saya sendiri:
Ini membuat banyak skema otentikasi TENANG mustahil atau konyol jika Anda berniat untuk menggunakan klien JavaScript. Mari lihat!
HTTP Basic Auth
Pertama dan terpenting, HTTP Basic Auth. Skema yang paling sederhana: cukup berikan nama dan kata sandi dengan setiap permintaan.
Ini, tentu saja, benar-benar memerlukan SSL, karena Anda memberikan nama dan kata sandi yang disandikan Base64 (reversibel) dengan setiap permintaan. Siapa pun yang mendengarkan di saluran dapat mengekstraksi nama pengguna dan kata sandi sepele. Sebagian besar argumen "Basic Auth is insecure" berasal dari tempat "Basic Auth over HTTP" yang merupakan ide buruk.
Peramban menyediakan dukungan HTTP Basic Auth yang dipanggang, tetapi itu jelek dan Anda seharusnya tidak menggunakannya untuk aplikasi Anda. Namun alternatifnya adalah menyembunyikan nama pengguna dan kata sandi dalam JavaScript.
Ini adalah solusi yang paling tenang. Server tidak memerlukan pengetahuan tentang keadaan apa pun dan mengotentikasi setiap interaksi individu dengan pengguna. Beberapa penggemar REST (kebanyakan strawmen) bersikeras bahwa mempertahankan segala bentuk negara adalah bid'ah dan akan berbusa di mulut jika Anda memikirkan metode otentikasi lainnya. Ada manfaat teoretis untuk kepatuhan standar seperti ini - didukung oleh Apache di luar kotak - Anda dapat menyimpan objek Anda sebagai file dalam folder yang dilindungi oleh file .htaccess jika hati Anda menginginkannya!
The masalah ? Anda caching di sisi klien nama pengguna dan kata sandi. Hal ini memberikan celah yang lebih baik bagi evil.ru - bahkan kerentanan XSS yang paling dasar dapat mengakibatkan klien mengirimkan nama pengguna dan kata sandi ke server jahat. Anda dapat mencoba mengurangi risiko ini dengan hashing dan salting password, tetapi ingat: JavaScript Crypto is Hopeless . Anda dapat mengurangi risiko ini dengan menyerahkannya ke dukungan Auth Basic Browser, tetapi .. jelek seperti dosa, seperti yang disebutkan sebelumnya.
HTTP Digest Auth
Apakah otentikasi Digest dapat dilakukan dengan jQuery?
Auth yang lebih "aman", ini adalah tantangan hash permintaan / respons. Kecuali JavaScript, Crypto tidak memiliki harapan , sehingga hanya berfungsi di atas SSL dan Anda masih harus men-cache nama pengguna dan kata sandi di sisi klien, membuatnya lebih rumit daripada HTTP Auth Dasar tapi tidak lebih aman .
Otentikasi kueri dengan Parameter Tanda Tangan Tambahan.
Auth lain yang lebih "aman", di mana Anda mengenkripsi parameter Anda dengan data nonce dan timing (untuk melindungi terhadap serangan repeat dan timing) dan mengirimkan. Salah satu contoh terbaik dari hal ini adalah protokol OAuth 1.0, yang sejauh yang saya tahu, merupakan cara yang sangat sulit untuk mengimplementasikan otentikasi pada server REST.
http://tools.ietf.org/html/rfc5849
Oh, tapi tidak ada klien OAuth 1.0 untuk JavaScript. Mengapa?
JavaScript Crypto Tidak Ada Harapan , ingat. JavaScript tidak dapat berpartisipasi dalam OAuth 1.0 tanpa SSL, dan Anda masih harus menyimpan nama pengguna dan kata sandi klien secara lokal - yang menempatkan ini dalam kategori yang sama dengan Digest Auth - ini lebih rumit daripada HTTP Basic Auth tetapi tidak lebih aman .
Token
Pengguna mengirimkan nama pengguna dan kata sandi, dan sebagai gantinya mendapat token yang dapat digunakan untuk mengotentikasi permintaan.
Ini sedikit lebih aman daripada HTTP Basic Auth, karena begitu transaksi nama pengguna / kata sandi selesai, Anda dapat membuang data sensitif. Ini juga kurang tenang, karena token merupakan "negara" dan membuat implementasi server lebih rumit.
SSL Masih
Namun, masalahnya, Anda masih harus mengirim nama pengguna dan kata sandi awal itu untuk mendapatkan token. Informasi sensitif masih menyentuh JavaScript Anda yang dapat dikompromikan.
Untuk melindungi kredensial pengguna Anda, Anda masih harus menjaga penyerang keluar dari JavaScript Anda, dan Anda masih perlu mengirim nama pengguna dan kata sandi melalui kabel. Diperlukan SSL.
Token Kadaluwarsa
Sudah umum untuk menerapkan kebijakan token seperti "hei, ketika token ini sudah terlalu lama, buang dan buat pengguna mengautentikasi lagi." atau "Saya cukup yakin bahwa satu-satunya alamat IP yang diizinkan menggunakan token ini adalah
XXX.XXX.XXX.XXX
". Banyak dari kebijakan ini adalah ide yang cukup bagus.Perapian
Namun, menggunakan token Tanpa SSL masih rentan terhadap serangan yang disebut 'sidejacking': http://codebutler.github.io/firesheep/
Penyerang tidak mendapatkan kredensial pengguna Anda, tetapi mereka masih bisa berpura-pura menjadi pengguna Anda, yang bisa sangat buruk.
tl; dr: Mengirim token yang tidak dienkripsi di atas kawat berarti bahwa penyerang dapat dengan mudah menangkap token itu dan berpura-pura menjadi pengguna Anda. FireSheep adalah program yang membuatnya sangat mudah.
Zona Terpisah, Lebih Aman
Semakin besar aplikasi yang Anda jalankan, semakin sulit untuk memastikan bahwa mereka tidak akan dapat menyuntikkan beberapa kode yang mengubah cara Anda memproses data sensitif. Apakah Anda benar-benar mempercayai CDN Anda? Pengiklan Anda? Basis kode Anda sendiri?
Umum untuk perincian kartu kredit dan kurang umum untuk nama pengguna dan kata sandi - beberapa pelaksana menyimpan 'entri data sensitif' pada halaman terpisah dari aplikasi mereka yang lain, halaman yang dapat dikontrol dan dikunci sebaik mungkin, lebih disukai yang sulit untuk menipu pengguna dengan.
Cookie (artinya Token)
Dimungkinkan (dan umum) untuk memasukkan token otentikasi ke dalam cookie. Ini tidak mengubah salah satu properti auth dengan token, itu lebih merupakan hal yang mudah. Semua argumen sebelumnya masih berlaku.
Sesi (masih berarti Token)
Session Auth hanyalah otentikasi Token, tetapi dengan beberapa perbedaan yang membuatnya tampak seperti hal yang sedikit berbeda:
Selain itu, sebenarnya tidak ada bedanya dengan Token Auth.
Ini mengembara lebih jauh dari implementasi RESTful - dengan objek negara Anda akan semakin jauh di jalur RPC biasa di server stateful.
OAuth 2.0
OAuth 2.0 melihat masalah "Bagaimana Perangkat Lunak A memberi akses Perangkat Lunak B ke data Pengguna X tanpa Perangkat B memiliki akses ke kredensial login Pengguna X."
Implementasinya sangat sederhana hanya cara standar bagi pengguna untuk mendapatkan token, dan kemudian untuk layanan pihak ketiga untuk pergi "ya, pengguna ini dan kecocokan token ini, dan Anda bisa mendapatkan beberapa data mereka dari kami sekarang."
Namun, pada dasarnya, OAuth 2.0 hanyalah sebuah protokol token. Ini menunjukkan properti yang sama dengan protokol token lainnya - Anda masih membutuhkan SSL untuk melindungi token tersebut - itu hanya mengubah cara token tersebut dihasilkan.
Ada dua cara yang OAuth 2.0 dapat membantu Anda:
Tapi ketika tiba saatnya, Anda hanya ... menggunakan token.
Kembali ke pertanyaan Anda
Jadi, pertanyaan yang Anda tanyakan adalah "haruskah saya menyimpan token saya di cookie dan manajemen sesi otomatis lingkungan saya mengurus detailnya, atau haruskah saya menyimpan token saya di Javascript dan menangani detail itu sendiri?"
Dan jawabannya adalah: lakukan apa pun yang membuat Anda bahagia .
Masalahnya tentang manajemen sesi otomatis, adalah ada banyak keajaiban terjadi di belakang layar untuk Anda. Seringkali lebih baik untuk mengendalikan detail-detail itu sendiri.
Saya berusia 21 tahun sehingga SSL adalah ya
Jawaban lainnya adalah: Gunakan https untuk semuanya atau perampok akan mencuri kata sandi dan token pengguna Anda.
sumber
It's also less RESTful, as tokens constitute "state and make the server implementation more complicated."
(1) REST mengharuskan server menjadi stateless. Sisi klien yang disimpan token tidak mewakili keadaan dengan cara apa pun yang berarti untuk server. (2) Kode sisi server yang sedikit lebih rumit tidak ada hubungannya dengan RESTfulness.lol_nope_send_it_to_me_instead
Saya menyukai nama fungsi ini: DAnda dapat meningkatkan keamanan dalam proses otentikasi dengan menggunakan JWT (JSON Web Tokens) dan SSL / HTTPS.
ID Auth / Sesi Dasar dapat dicuri melalui:
Dengan menggunakan JWT Anda mengenkripsi detail otentikasi pengguna dan menyimpannya di klien, dan mengirimkannya bersama setiap permintaan ke API, di mana server / API memvalidasi token.
Itu tidak dapat didekripsi / dibaca tanpa kunci pribadi (yang disimpan secara diam-diam oleh server / API).Baca pembaruan .Aliran baru (lebih aman) adalah:
Gabung
Setiap permintaan ke API
Diperbarui 30.07.15:
Muatan / klaim JWT sebenarnya dapat dibaca tanpa kunci pribadi (rahasia) dan tidak aman untuk menyimpannya di Penyimpanan lokal. Saya minta maaf tentang pernyataan palsu ini. Namun mereka tampaknya bekerja pada standar JWE (JSON Web Encryption) .
Saya menerapkan ini dengan menyimpan klaim (userID, exp) di JWT, menandatanganinya dengan kunci pribadi (rahasia) API / backend hanya tahu tentang dan menyimpannya sebagai cookie HttpOnly aman pada klien. Dengan cara itu tidak dapat dibaca melalui XSS dan tidak dapat dimanipulasi, jika tidak JWT gagal verifikasi tanda tangan. Juga dengan menggunakan cookie HttpOnly yang aman , Anda memastikan bahwa cookie tersebut dikirim hanya melalui permintaan HTTP (tidak dapat diakses ke skrip) dan hanya dikirim melalui koneksi aman (HTTPS).
Diperbarui 17.07.16:
JWT pada dasarnya tidak memiliki kewarganegaraan. Itu berarti mereka membatalkan / kedaluwarsa sendiri. Dengan menambahkan SessionID di klaim token yang Anda buat statusnya, karena validitasnya sekarang tidak hanya bergantung pada verifikasi tanda tangan dan tanggal kedaluwarsa, itu juga tergantung pada status sesi di server. Namun kelebihannya adalah Anda dapat membatalkan token / sesi dengan mudah, yang sebelumnya tidak dapat Anda lakukan dengan JWT yang tidak memiliki kewarganegaraan.
sumber
Saya akan memilih yang kedua, sistem token.
Tahukah Anda tentang bara-auth atau bara-sederhana-auth ? Keduanya menggunakan sistem berbasis token, seperti status bara-sederhana-auth:
Mereka memiliki manajemen sesi, dan mudah untuk dihubungkan ke proyek yang ada juga.
Ada juga Ember App Kit versi contoh bara-simple-auth: Contoh kerja bara-app-kit menggunakan bara-simple-auth untuk otentikasi OAuth2.
sumber