OAuth2 ROPC vs Basic Auth untuk API REST publik?

21

Kasus penggunaan khusus yang saya tertarik di sini adalah mengautentikasi REST klien terhadap titik akhir server yang tersedia untuk umum (seperti API REST publik).

Solusi paling sederhana di sini adalah Auth Dasar . Tapi saya sering mendengar OAuth2 disebut-sebut sebagai solusi auth superior di hampir semua keadaan.

Masalahnya adalah, satu - satunya jenis hibah OAuth2 yang layak untuk klien REST yang diautentikasi terhadap server REST adalah Kredensial Kata Sandi Pemilik Sumber Daya (ROPC) , karena Hibah Kode dan Hibah Tersirat memerlukan UI / halaman web (dihosting oleh Server Auth) untuk pengguna untuk masuk dan mengotorisasi aplikasi klien secara manual.

Cara ROPC bekerja adalah, dengan mengirim nama pengguna / kata sandi pemilik sumber daya, dan ID klien sebagai params string kueri ?!? Ini bahkan lebih tidak aman (IMHO) daripada Basic Auth, yang setidaknya base-64 mengkodekan kredensial dan mengirimkannya di dalam header yang dapat dienkripsi oleh TLS!

Jadi saya bertanya: dalam konteks API REST publik, apakah OAuth2 ROPC benar - benar lebih baik daripada Auth Dasar? Apa yang lebih aman daripada OAuth2 ROPC?


Memperbarui

Saya baru saja membaca artikel yang luar biasa ini yang menjelaskan keamanan REST berbasis non-OAuth2 untuk AWS di Amazon. Ini pada dasarnya adalah solusi berbasis kunci pribadi di mana hash dari setiap permintaan REST dihasilkan dan dikirim sebagai sidecars di samping permintaan normal (tidak terenkripsi). Hanya klien dan server yang mengetahui kunci privat, jadi ketika server menerima permintaan (sekali lagi, berisi permintaan normal + permintaan hash), server mencari kunci privat klien, menerapkan hash yang sama dengan permintaan normal, dan kemudian membandingkan dua hash.

Ini kedengarannya jauh lebih rumit, rumit dan aman daripada ROPC OAuth2! Kecuali saya kehilangan sesuatu yang utama di sini, OAuth2 ROPC baru saja mengirim client_id, usernamedan passwordsebagai params string permintaan ... sama sekali dan benar-benar tidak aman! Solusi berbasis HMAC / hash ini tampaknya jauh lebih mengesankan dan aman.

Masalahnya adalah, bahkan penulis artikel itu selanjutnya mengatakan:

Anda [akan] juga perlahan-lahan menyadari dan menerima bahwa pada titik tertentu Anda harus menerapkan OAuth ...

Ba-ba-bapa?!?! Jika OAuth2 kurang aman dibandingkan solusi berbasis HMAC / hash yang pintar ini, mengapa penulis artikel ini merasa OAuth perlu dipeluk di beberapa titik. Aku begitu bingung.

smeeb
sumber
Klien apa yang sedang Anda bicarakan? Saya berasumsi bahwa sebagian besar klien akan memiliki UI. Dalam hal ini, Anda dapat memuat halaman login OAuth dalam tampilan web (desktop, seluler) atau mengarahkan langsung ke halaman itu (web). Saya tidak mengerti mengapa Anda harus menghindari UI.
decyclone
@decyclone, harap baca kalimat pertama dari pertanyaan! Saya membahas klien REST (headless HTTP) yang mengautentikasi terhadap layanan REST.
smeeb
Pertanyaan yang saya tanyakan adalah apakah klien itu memiliki UI sama sekali? Bahkan jika tidak, saya telah melihat aplikasi tanpa UI memunculkan dialog setidaknya untuk otentikasi.
Decyclone
@decyclone no REST klien murni tidak memiliki UI apa pun, meskipun UI biasanya menggunakan klien REST murni untuk menghubungkan ke layanan REST. Satu kasus penggunaan adalah alat baris perintah yang menggunakan klien REST untuk mengirim perintah pengguna (dimasukkan pada shell) ke layanan REST. Popping UI dari shell bukan merupakan solusi yang dapat diterima di sini.
smeeb
1
Tapi, saya harus perhatikan, ada banyak kasus penggunaan lain di luar baris perintah / shell. Kasus penggunaan lain adalah klien REST / HTTP murni Java / Ruby / Python yang tidak memiliki UI dan mungkin berjalan pada server backend yang tidak memiliki UI. Server backend perlu berkomunikasi dengan server backend lain melalui REST. Di sini, tidak hanya akan aneh dan meretas untuk mengeluarkan UI ketika server backend # 1 perlu berbicara dengan server backend # 2, masalah sebenarnya tidak ada browser / klien UI untuk menampilkan halaman login, dan tidak ada manusia berada di sana untuk masuk !!!
smeeb

Jawaban:

24

Jawaban atas pertanyaan Anda bisa di level kode, level protokol atau level arsitektur. Saya akan mencoba untuk meringkas di sini sebagian besar masalah tingkat protokol karena itu biasanya penting dalam analisis pro dan kontra. Perlu diingat bahwa OAuth2 lebih dari sekadar Kredensial Kata Sandi Pemilik Sumber Daya yang, menurut spesifikasi, ada karena "alasan warisan atau migrasi", dianggap "risiko lebih tinggi daripada jenis hibah lainnya" dan spesifikasi secara eksplisit menyatakan bahwa klien dan server otorisasi "HARUS meminimalkan penggunaan jenis hibah ini dan menggunakan jenis hibah lainnya bila memungkinkan".

Masih banyak keuntungan menggunakan ROPC dibandingkan otentikasi dasar tetapi sebelum kita membahasnya, mari kita pahami perbedaan protokol dasar antara OAuth2 dan otentikasi dasar. Tolong ikut saya saat saya menjelaskan ini dan akan datang ke ROPC nanti.

Otentikasi pengguna mengalir

Ada empat peran yang ditentukan dalam spesifikasi OAuth2. Dengan contoh, mereka adalah:

  1. Pemilik sumber daya: Pengguna yang memiliki akses ke beberapa sumber daya, misalnya dalam kasus Anda, pengguna yang berbeda mungkin memiliki tingkat akses yang berbeda ke REST API;
  2. Klien: biasanya aplikasi yang digunakan pengguna, dan membutuhkan akses ke sumber daya untuk menyediakan layanan kepada pengguna;
  3. Server sumber daya: API REST dalam kasus Anda; dan
  4. Server otorisasi: server tempat kredensial pengguna disajikan dan yang akan mengotentikasi pengguna.

Ketika aplikasi klien berjalan, itu diberikan akses ke sumber daya berdasarkan pengguna. Jika pengguna memiliki hak administrator, sumber daya dan operasi yang tersedia untuk pengguna di REST API mungkin jauh lebih dari pengguna tanpa hak administrator.

OAuth2 juga memungkinkan kemungkinan menggunakan server otorisasi tunggal dengan banyak klien dan untuk banyak sumber daya. Sebagai contoh, server sumber daya dapat menerima otentikasi pengguna dengan Facebook (yang dapat bertindak sebagai server otorisasi dalam kasus seperti itu). Jadi ketika pengguna menjalankan aplikasi (yaitu klien), ia mengirimkan pengguna ke Facebook. Pengguna mengetik kredensial mereka di Facebook, dan klien mendapatkan kembali "token" yang dapat disajikan ke server sumber daya. Server sumber daya melihat token dan menerimanya setelah memverifikasi bahwa Facebook sebenarnya mengeluarkannya dan memungkinkan pengguna mengakses sumber daya tersebut. Dalam hal ini, klien tidak pernah melihat kredensial pengguna (yaitu kredensial Facebook mereka).

Tetapi katakanlah Anda mengelola identitas pengguna Anda (dan memiliki server otorisasi) alih-alih Facebook, yang sudah memberi token kepada klien Anda. Sekarang, katakanlah Anda juga memiliki mitra dan Anda ingin mengizinkan aplikasi mereka (yaitu klien) untuk mengakses API REST Anda. Dengan otentikasi dasar (atau bahkan ROPC), pengguna akan memberikan kredensial kepada klien yang akan mengirimkannya ke server otorisasi. Server otorisasi kemudian akan memberikan token yang dapat digunakan oleh klien untuk mengakses sumber daya. Sayangnya, ini berarti kredensial pengguna sekarang juga dapat dilihat oleh klien itu. Namun, Anda tidak ingin aplikasi mitra (yang mungkin berasal dari luar organisasi Anda) bahkan mengetahui kata sandi pengguna. Itu masalah keamanan sekarang. Untuk mencapai tujuan itu,

Jadi, dengan OAuth2, idealnya tidak menggunakan ROPC dalam kasus seperti itu daripada menggunakan yang berbeda, seperti aliran kode otorisasi. Ini melindungi aplikasi apa pun dari mengetahui kredensial pengguna yang disajikan hanya ke server otorisasi. Dengan demikian, kredensial pengguna tidak bocor. Masalah yang sama berlaku dengan otentikasi dasar, tetapi di bagian berikutnya, saya akan menjelaskan bagaimana ROPC masih lebih baik karena kredensial pengguna masih tidak perlu disimpan oleh klien di ROPC untuk akses terus-menerus oleh klien.

Perhatikan bahwa ketika pengguna pergi ke server otorisasi, server otorisasi juga dapat meminta pengguna untuk mengonfirmasi bahwa mereka ingin mengizinkan klien untuk mengakses sumber daya atas nama mereka atau tidak. Itulah mengapa ini disebut server otorisasi karena proses otorisasi klien untuk mengakses sumber daya diperlukan dalam proses. Jika pengguna tidak mengotorisasi klien, itu tidak akan mendapatkan akses ke sumber daya. Demikian juga, jika pengguna itu sendiri tidak memiliki akses ke sumber daya, server otorisasi masih dapat menolak akses dan tidak mengeluarkan token.

Dalam otentikasi dasar, bahkan server otorisasi dan server sumber daya digabungkan menjadi satu kesatuan. Dengan demikian, server sumber daya ingin mengotorisasi pengguna, jadi tanyakan kredensial dari klien. Klien melengkapi kredensial yang digunakan oleh server sumber daya untuk mengautentikasi pengguna. Ini berarti bahwa beberapa server sumber daya pada dasarnya akan memerlukan kredensial dari pengguna.

Penerbitan token

Klien mendapatkan token dari server otorisasi, menyimpannya dan menggunakannya untuk mengakses sumber daya (detail lebih lanjut tentang token sendiri di bawah). Klien tidak pernah tahu kata sandi pengguna (dalam aliran selain ROPC) dan tidak perlu menyimpannya. Di ROPC, meskipun klien mengetahui kata sandi pengguna, mereka masih tidak perlu menyimpannya karena mereka menggunakan token ini untuk mengakses sumber daya. Sebaliknya, dalam otentikasi dasar, jika klien tidak ingin memiliki pengguna untuk memberikan kredensial di setiap sesi, maka klien harus menyimpan kata sandi pengguna sehingga mereka dapat memberikannya di waktu berikutnya. Ini adalah kelemahan utama untuk menggunakan otentikasi dasar kecuali jika klien hanya aplikasi web dalam hal ini, cookie dapat mengatasi beberapa masalah ini. Dengan aplikasi asli, itu biasanya bukan opsi.

Ada aspek lain dari OAuth2 yang mensyaratkan bagaimana token dikeluarkan dan mereka bekerja. Ketika pengguna memberikan kredensial ke server otorisasi (bahkan di ROPC), server otorisasi dapat memberikan satu atau lebih dari dua jenis token: 1) token akses, dan 2) token refresh.

Token akses dikirim ke server sumber daya yang akan memberikan akses ke sumber daya setelah memvalidasi itu, dan biasanya mereka memiliki masa hidup yang singkat, misalnya 1 jam. Refresh token dikirim ke server otorisasi oleh klien untuk mendapatkan token akses lain ketika berakhir, dan biasanya memiliki masa pakai yang besar (mis. Beberapa hari hingga beberapa bulan atau bahkan bertahun-tahun).

Ketika klien memberikan token akses ke server sumber daya, ia melihat token dan setelah memvalidasi, mencari di dalam token untuk menentukan apakah akan mengizinkan akses atau tidak. Selama token akses valid, klien dapat terus menggunakannya. Katakanlah pengguna menutup aplikasi dan memulainya pada hari berikutnya, dan token akses telah kedaluwarsa. Sekarang klien akan melakukan panggilan ke server otorisasi dan menyajikan token penyegaran dengan asumsi itu tidak kedaluwarsa. Server otorisasi, karena sudah mengeluarkan token, memverifikasinya dan dapat menentukan bahwa pengguna tidak perlu memberikan kredensial lagi dan dengan demikian memberikan token akses lain kepada klien. Klien sekarang memiliki akses ke server sumber daya lagi. Ini adalah bagaimana biasanya aplikasi klien untuk Facebook dan Twitter meminta kredensial satu kali dan kemudian tidak mengharuskan pengguna untuk memberikan kredensial lagi. Aplikasi ini tidak perlu mengetahui kredensial pengguna dan dapat mengakses sumber daya setiap kali pengguna memulai aplikasi.

Sekarang pengguna dapat masuk ke server otorisasi (misalnya di profil pengguna Facebook mereka), mengubah kata sandi tanpa memengaruhi aplikasi klien apa pun. Mereka semua akan terus berfungsi dengan baik. Jika pengguna kehilangan perangkat yang sudah memiliki aplikasi dengan token penyegaran, mereka dapat memberi tahu server otorisasi (mis. Facebook) untuk "mengeluarkannya" dari aplikasi-aplikasi yang akan diselesaikan oleh server otorisasi (yaitu Facebook) dengan tidak menghormati yang sudah ada menyegarkan token dan memaksa pengguna untuk memberikan kredensial lagi ketika mereka mencoba mengakses sumber daya melalui aplikasi tersebut.

JWT hanyalah format token yang biasanya digunakan dengan OAuth2 dan OpenID Connect. Metode penandatanganan token dan memvalidasi itu juga distandarisasi dengan perpustakaan yang tersedia untuk mereka daripada setiap server sumber daya menerapkan solusi lain. Dengan demikian, keuntungannya terletak pada penggunaan kembali kode yang telah diperiksa dan terus didukung.

Implikasi keamanan

Otentikasi dasar akan lebih lemah ketika ada skenario di atas dalam gambar. Ada juga model ancaman yang luas untuk OAuth2 yang tersedia untuk pengembang yang dapat menggunakan saran di dalamnya untuk menghindari kerentanan umum dalam implementasi mereka. Jika Anda melihat model ancaman, Anda akan melihat bahwa banyak kerentanan terkait implementasi (seperti pengalihan terbuka dan CSRF) juga tercakup di dalamnya. Saya tidak melalui perbandingan yang terhadap otentikasi dasar dalam respons ini.

Keuntungan utama terakhir dari OAuth2 adalah protokolnya distandarisasi dan beberapa server otorisasi, klien dan server sumber menghargainya. Banyak perpustakaan tersedia untuk pengembang, yang dikelola sehingga masalah keamanan ditemukan dalam implementasi, perpustakaan diperbarui sambil memungkinkan interoperabilitas.

Kesimpulan

Jika Anda menulis aplikasi baru, IMO, kasus yang ideal adalah menghindari otentikasi dasar dan ROPC karena masalah yang melekat di dalamnya. Namun, setiap aplikasi memiliki kebutuhan yang berbeda, jadwal, kemampuan pengembang dll. Sehingga keputusannya adalah kasus per kasus. Tetapi bahkan jika Anda tidak memiliki kebutuhan lebih dari otentikasi dasar, dengan memilihnya, Anda dapat mengunci diri sendiri ke dalam arsitektur yang mungkin tidak mudah untuk diperluas (mis. Jika Anda memiliki beberapa server di masa depan, Anda tidak perlu ingin memiliki pengguna memberikan kredensial kepada mereka masing-masing alih-alih hanya memberikan ke server otorisasi satu kali, yang dapat membagikan token, dll.)

Perhatikan bahwa saya tidak membahas komentar Anda tentang bagaimana kredensial dikirim melalui kawat karena mereka dapat diamankan menggunakan TLS atau protokol serupa, atau bukti kepemilikan dll. Seperti yang telah disarankan seseorang, pengkodean basis 64 adalah 0 keamanan, tolong jangan tertipu oleh itu. Perbedaan yang disebutkan di atas biasanya pada tingkat arsitektur dan karena itu di mana saya fokus karena arsitektur adalah yang paling sulit untuk berubah setelah diimplementasikan.

Azure Active Directory B2C Basic , layanan yang saya kerjakan dan baru-baru ini dirilis untuk pratinjau publik, memungkinkan aplikasi pihak ketiga untuk menggunakan AAD sebagai server otorisasi dengan interoperabilitas dengan IDP sosial (seperti Facebook, Google, dll.). Ini juga memungkinkan pengguna untuk membuat akun mereka sendiri daripada menggunakan IDP sosial dan yang nantinya dapat digunakan untuk tujuan otentikasi. Ada beberapa layanan lain juga seperti itu (misalnya yang saya tahu adalah auth0) yang dapat digunakan oleh pengembang untuk sepenuhnya melakukan outsourcing otentikasi dan manajemen pengguna untuk aplikasi dan sumber daya mereka. Karakteristik protokol yang sama yang saya sebutkan di atas digunakan oleh pengembang untuk memisahkan server otorisasi (AAD), sumber daya (misalnya API REST mereka), klien (misalnya aplikasi seluler mereka), dan pengguna. Saya harap penjelasan ini agak membantu.

Omer Iqbal
sumber
Terima kasih untuk sudut lebar, tapi saya tidak berpikir kelebihan ini, (a) letting the user agent hold just the token instead of the password, (b) allowing a password change without disrupting existing client apps, (c) allowing users log out other sessionskhusus untuk aliran otentikasi token. Otentikasi Basic atau token tidak menyebutkan fungsi (b) dan (c) dalam spesifikasi mereka. Menerapkan (b) dan (c) tampaknya memungkinkan untuk segala jenis otentikasi. Ini akan melibatkan melacak kata sandi (lebih disukai hash mereka). Keuntungan (a) tampaknya tergantung pada ruang lingkup kata sandi yang lebih luas.
belut ghEEz
Bagaimana kita bisa menggunakan OAuth jika pengguna (Pemilik Sumber Daya) tidak memiliki kredensial dengan server Otorisasi eksternal, tetapi ia memiliki kredensial dalam aplikasi Klien? Itu adalah kami memiliki Pemilik Sumber Daya (pengguna), Klien (mewakili pengguna & juga berisi kredensial untuk pengguna) dan Server Sumber Daya. Bagaimana Server Sumber Daya mengotentikasi & mengotorisasi pengguna?
Arun Avanathan
3

Saya yakin Anda salah informasi tentang enkripsi di sekitar variabel GET dalam URL

Satu-satunya orang yang dapat melihat variabel GET dalam permintaan adalah komputer asli dan server penerima ( tautan ).

Hanya pencarian DNS berdasarkan domain yang permintaan HTTPS dikirim ke tidak dienkripsi. Yang lainnya, porta, variabel GET, ID sumber daya, dienkripsi.

Satu-satunya peringatan untuk itu adalah bahwa server penerima dapat log keluar dari jalur permintaan penuh, tetapi Anda mengendalikannya sehingga Anda dapat melindungi data itu sesuai keinginan Anda.

Patrick
sumber
3

Otentikasi dasar bukan cara yang baik untuk mengamankan API REST Anda. Saya menjelaskan alasan mengapa dalam jawaban ini .

Saat Anda membangun REST API, Anda menerapkan server sumber daya dalam istilah OAuth2. Semua yang perlu dilakukan oleh API Anda adalah memvalidasi bahwa token yang dikirimkan bersama dengan permintaan di header HTTP Otorisasi valid dan dari penerbit tepercaya. Lihat tautan ini untuk langkah-langkah cara menerapkan validasi jika tidak ada perpustakaan yang tersedia.

Bagaimana klien Anda memperoleh token dari server otorisasi tergantung pada jenis klien itu. Ingat, Anda perlu menentukan jenis klien yang akan Anda gunakan ketika Anda mendaftarkan klien dengan server otorisasi.

Jika ada aplikasi web yang berbicara dengan server Anda, itu bisa menggunakan hibah kode otorisasi . Jika klien tidak tepercaya seperti aplikasi seluler atau aplikasi JavaScript, itu harus menggunakan hibah implisit .

Untuk layanan backend yang tidak dapat berinteraksi dengan pemilik sumber daya, Anda dapat menggunakan hibah kredensial klien . Untuk alat baris perintah, Anda bisa menggunakan kredensial klien atau pemberian kata sandi pemilik sumber daya .

Itu semua tergantung pada jenis klien yang Anda gunakan.

Akhirnya, memvalidasi token JWT terjadi pada server sumber daya tanpa perlu berbicara dengan server otorisasi. Ini mengarah pada arsitektur yang lebih skalabel dari pada solusi yang perlu mencari data pribadi untuk setiap klien.

MvdD
sumber
1

Itu aman atau tidak aman. Tidak lebih, tidak kurang. Memiliki base64 tidak membuat Auth Dasar (atau apa pun) lebih aman.

Tidak ada yang salah dalam mengirim sesuatu yang tidak terenkripsi jika menggunakan pipa terenkripsi seperti Https.

OAuth memiliki lebih banyak fitur, gunakan jika Anda membutuhkannya. Untuk hal lain, misalnya perbankan, menggunakan tantangan-respons dasar baik dan aman.

imel96
sumber
0

Saya pikir Anda perlu memahami terminologinya terlebih dahulu. Anda membandingkan- Otorisasi dan tanda tangan Digital

OAuth adalah standar terbuka untuk Otorisasi , di mana apa yang dilakukan amazon (sesuai artikel dan detail yang diberikan dalam pertanyaan Anda) adalah menciptakan tanda tangan digital yang valid yang memberikan alasan kepada penerima (di sini Amazon) untuk percaya bahwa pesan itu dibuat oleh orang yang dikenal pengirim, bahwa pengirim tidak dapat menyangkal telah mengirim pesan ( otentikasi dan non-penolakan)

Untuk mekanisme otorisasi mana yang digunakan, itu lebih atau kurang tergantung pada kasus penggunaan Anda.

Di bawah ini adalah apa yang dapat ditemukan di StackOverflow di sini :

Otentikasi dasar yang memerlukan hashing yang sangat sederhana untuk menghitung header tunggal yang diperlukan - OAuth tanpa diragukan lagi otentikasi yang lebih mahal. Yang penting untuk disadari adalah bahwa dua mekanisme otentikasi melayani tujuan yang sama sekali berbeda. Auth dasar adalah untuk mengautentikasi klien ke aplikasi utama. OAuth adalah untuk mengotorisasi pihak ketiga untuk mengakses data klien dari aplikasi utama. Keduanya memiliki tempat masing-masing dan memilih satu di antara yang lain harus didorong oleh kasus penggunaan tertentu dari implementasi.

Dan di sini ada artikel menarik yang membandingkan keduanya.

Otentikasi dasar melalui SSL sebenarnya cukup bertanggung jawab, dari sudut pandang keamanan sederhana. Ketika kita bersaing dengan nama pengguna dan kata sandi, otentikasi Dasar adalah solusi yang lazim karena sangat mudah untuk diterapkan. Transmisi kredensial dienkripsi melalui SSL, dan penggunaan header "Otorisasi" ada di mana-mana di klien dan sistem HTTP.

Guanxi
sumber