Mengapa ada "Kode Otorisasi" mengalir di OAuth2 ketika aliran "Implisit" bekerja dengan sangat baik?

264

Dengan aliran "Tersirat", klien (kemungkinan peramban) akan mendapatkan token akses, setelah Pemilik Sumber Daya (yaitu pengguna) memberikan akses.

Namun dengan aliran "Kode Otorisasi", klien (biasanya server web) hanya mendapatkan kode otorisasi setelah Pemilik Sumber Daya (yaitu pengguna) memberikan akses. Dengan kode otorisasi itu, klien kemudian melakukan panggilan lain ke API yang meneruskan client_id dan client_secret bersama dengan kode otorisasi untuk mendapatkan token akses. Semua dijelaskan dengan baik di sini .

Kedua aliran memiliki hasil yang sama persis: token akses. Namun, aliran "Tersirat" jauh lebih sederhana.

Pertanyaannya: Mengapa repot-repot dengan "Kode Otorisasi" mengalir, ketika aliran "Implisit" terlihat baik-baik saja? Mengapa tidak menggunakan "Implisit" untuk server web?

Lebih banyak pekerjaan untuk penyedia dan klien.

Aron Woost
sumber
1
Terima kasih, sudah baca. Namun tidak menjawab pertanyaan.
Aron Woost
1
Pertanyaan yang bagus sebenarnya dan jarang dijawab :) Lihat di bawah.
Nicolas Garnier
1
@AronWoost Saya pikir Anda salah memahami aplikasi web Server dan aplikasi browser
onmyway133
@ Sentropi Itu pertanyaan saya; mengapa tidak menggunakan aliran browser untuk server juga.
Aron Woost

Jawaban:

293

tl; dr: Ini semua karena alasan keamanan.

OAuth 2.0 ingin memenuhi dua kriteria ini:

  1. Anda ingin mengizinkan pengembang untuk menggunakan URI pengalihan non-HTTPS karena tidak semua pengembang memiliki server berkemampuan SSL dan jika mereka tidak selalu dikonfigurasikan dengan benar (tidak ditandatangani sendiri, sertifikat SSL tepercaya, jam server yang disinkronkan ...).
  2. Anda tidak ingin peretas dapat mencuri akses / menyegarkan token dengan mencegat permintaan.

Detail di bawah:

Aliran implisit hanya mungkin di lingkungan browser karena alasan keamanan:

Dalam aliran implisit token akses dilewatkan secara langsung sebagai fragmen hash (bukan sebagai parameter URL). Satu hal penting tentang fragmen hash adalah bahwa, setelah Anda mengikuti tautan yang berisi fragmen hash, hanya browser yang mengetahui fragmen hash. Browser akan meneruskan fragmen hash langsung ke halaman web tujuan (URI redirect / halaman web klien). Hash fragment memiliki sifat-sifat berikut:

  • Mereka bukan bagian dari permintaan HTTP karena itu mereka tidak dapat dibaca oleh server dan karena itu mereka tidak dapat dicegat oleh server perantara / router (ini penting).
  • Mereka hanya ada di browser - sisi klien - jadi satu-satunya cara untuk membaca fragmen hash menggunakan JavaScript yang berjalan di halaman.

Ini memungkinkan untuk melewatkan Token Akses langsung ke klien tanpa risiko diinterupsi oleh server perantara. Ini memiliki peringatan hanya menjadi sisi klien yang mungkin dan perlu javascript menjalankan sisi klien untuk menggunakan token akses.

Aliran implisit juga memiliki masalah keamanan yang memerlukan logika lebih lanjut untuk menyelesaikan / menghindari misalnya:

  • Seorang penyerang bisa mendapatkan token akses dari pengguna di situs web / aplikasi lain (katakanlah jika dia adalah pemilik situs web / aplikasi lain), catat token di situs web mereka, dan kemudian berikan sebagai parameter URL di situs web Anda karena itu menyamar sebagai pengguna di situs web Anda. Untuk menghindari hal ini, Anda perlu memeriksa ID Klien yang terkait dengan token akses (misalnya untuk Google Anda dapat menggunakan titik akhir tokeninfo) untuk memastikan token itu dikeluarkan dengan ID klien Anda sendiri (yaitu dengan aplikasi Anda sendiri) atau periksa tanda tangan jika Anda menggunakan IDToken (tetapi itu membutuhkan rahasia klien Anda).
  • Jika permintaan auth bukan berasal dari properti Anda sendiri (disebut Session Fixation attack), untuk menghindari ini, Anda ingin membuat hash acak dari situs web Anda, menyimpannya dalam cookie dan meneruskan hash yang sama di URL URL param permintaan auth, ketika pengguna kembali Anda memeriksa param negara dengan cookie dan itu harus cocok.

Dalam aliran kode otorisasi tidak mungkin untuk melewatkan token akses secara langsung dalam parameter URL karena parameter URL adalah bagian dari Permintaan HTTP, oleh karena itu setiap server perantara / router tempat permintaan Anda akan melewati (bisa ratusan) dapat baca token akses jika Anda tidak menggunakan koneksi terenkripsi (HTTPS) yang memungkinkan apa yang dikenal sebagai serangan Man-in-the-middle.

Melewati token akses secara langsung dalam param URL dapat secara teori dimungkinkan tetapi auth sever harus memastikan URI redirect menggunakan HTTPS dengan enkripsi TLS dan sertifikat SSL 'tepercaya' (biasanya dari Otoritas Sertifikat yang tidak gratis) untuk memastikan bahwa server tujuan sah dan bahwa permintaan HTTP sepenuhnya terenkripsi. Memiliki semua pengembang membeli sertifikat SSL dan mengkonfigurasi SSL dengan benar di domain mereka akan sangat menyusahkan dan akan memperlambat adopsi. Inilah sebabnya mengapa "kode otorisasi" perantara sekali pakai diberikan asalkan hanya penerima yang sah yang dapat bertukar (karena Anda memerlukan rahasia klien) dan bahwa kode tersebut tidak akan berguna bagi peretas potensial yang mencegat permintaan atas transaksi yang tidak dienkripsi. (karena mereka tidak

Anda juga bisa berpendapat bahwa aliran implisit kurang aman, ada vektor serangan potensial seperti spoofing domain saat pengalihan - misalnya dengan membajak alamat IP situs web klien. Ini adalah salah satu alasan mengapa aliran implisit hanya memberikan token akses (yang seharusnya memiliki waktu penggunaan terbatas) dan tidak pernah me-refresh token (yang tidak terbatas waktu). Untuk memperbaiki masalah ini, saya menyarankan Anda untuk meng-host halaman web Anda di server yang mendukung HTTPS bila memungkinkan.

Nicolas Garnier
sumber
12
@AndyDufresne Kedua permintaan ini harus dilakukan melalui HTTPS (wajib) karena mereka adalah permintaan ke server OAuth yang harus mendukung hanya HTTPS. Hanya server klien / pemohon yang tidak harus mendukung HTTPS, jadi hanya server yang Auth Codeberpotensi dikirim secara jelas melalui HTTP. Tetapi Auth Codetidak ada gunanya tanpa ID klien / Rahasia. Pada dasarnya inti dari aliran Kode OAuth adalah bahwa beban memiliki server yang mendukung SSL ada pada Penyedia OAuth (Google / Facebook dll ...) dan bukan pada pengguna API (Anda, saya).
Nicolas Garnier
5
Ok, sekarang saya ikuti bahwa kode auth dapat dilewatkan melalui HTTP biasa dan memiliki risiko menjadi mengendus. Menjadikannya satu kali menggunakan kode dan menerima rahasia klien untuk menukarnya dengan token akses, server otorisasi dapat mencegah serangan Man-in-the-middle. Tapi bukankah ini juga berlaku untuk token akses? Karena pengguna API bisa menggunakan HTTP biasa, bukankah akan ada risiko token akses yang diendus oleh peretas? PS - I Menghargai upaya Anda dalam menjelaskan konsep bahkan setelah beberapa saat sejak utas ini aktif. Terima kasih!
Andy Dufresne
8
no pb :) Permintaan ke API - yang mana ketika token akses dikirim melalui kawat (untuk mengotorisasi permintaan) - juga dilakukan melalui HTTPS secara wajib. Secara teori, klien tidak boleh mengirim token akses over-the-wire dalam HTTP biasa setiap saat.
Nicolas Garnier
5
Token Akses pada langkah ini adalah bagian dari respons permintaan HTTPS dari Klien ke server sumber daya. Respons ini masih dienkripsi.
Nicolas Garnier
13
Pada dasarnya permintaan yang dimulai dari klien ke server sumber daya dilakukan melalui HTTPS (karena server pemilik sumber daya harus mendukung dukungan HTTPS). Hanya permintaan yang dimulai dari tempat lain ke klien yang dapat dilakukan melalui HTTP (karena server klien mungkin tidak mendukung HTTPS). Misalnya pengalihan yang terjadi selama aliran auth setelah pengguna memberikan otorisasi pada halaman gant adalah pengalihan yang dimulai dari browser ke server klien dan dapat dilakukan dalam HTTP.
Nicolas Garnier
8

The Implisit Aliran membuat seluruh aliran cukup mudah, tetapi juga kurang aman .
Karena aplikasi klien, yang biasanya JavaScript yang berjalan di dalam Browser kurang tepercaya, tidak ada token penyegaran untuk akses jangka panjang yang dikembalikan.
Anda harus menggunakan aliran ini untuk aplikasi yang memerlukan akses sementara (beberapa jam) ke data pengguna.
Mengembalikan token akses ke klien JavaScript juga berarti bahwa aplikasi berbasis browser Anda harus berhati-hati - pikirkan XSS Attacks yang dapat membocorkan token akses ke sistem lain.

https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow

danau
sumber
Saya berharap bahwa ketika seseorang memiliki kerentanan XSS, maka bahkan aliran kode otorisasi tidak banyak membantu. Tapi saya setuju bahwa karena cara token akses diteruskan ke javascript dalam aliran Implisit distandarisasi (sebagai fragmen hash), dan jika ada kerentanan XSS di situs web, maka buat serangan yang membaca token akses dari hash URL fragmen cukup mudah. Dengan aliran kode otorisasi, di sisi lain, pemalsuan permintaan lintas situs mungkin dilakukan.
Marcel
Juga, ini bukan hanya tentang skrip lintas situs. Pustaka JavaScript apa pun yang berjalan di situs web Anda dapat mencoba mencuri token akses (misalnya pustaka CDN pihak ketiga atau pustaka sumber terbuka yang digunakan kerangka kerja javascript Anda).
Marcel
2
XSS bukan masalah besar saat ini ketika kami memiliki header Kebijakan Keamanan Konten dan hash Sub Resource Integrity (SRI).
Sergey Ponomarev
4

Dari spec OAuth :

4.2. Hibah Tersirat

Jenis hibah implisit digunakan untuk memperoleh token akses (itu tidak mendukung penerbitan token penyegaran) dan dioptimalkan untuk klien publik yang dikenal mengoperasikan URI redirection tertentu. Klien-klien ini biasanya diimplementasikan dalam browser menggunakan bahasa scripting seperti JavaScript.

Karena ini adalah aliran berbasis pengalihan, klien harus mampu berinteraksi dengan agen pengguna pemilik sumber daya (biasanya browser web) dan mampu menerima permintaan yang masuk (melalui pengalihan) dari server otorisasi.

Berbeda dengan jenis pemberian kode otorisasi, di mana klien membuat permintaan terpisah untuk otorisasi dan untuk token akses, klien menerima token akses sebagai hasil dari permintaan otorisasi.

Jenis hibah implisit tidak termasuk otentikasi klien, dan bergantung pada keberadaan pemilik sumber daya dan pendaftaran URI pengalihan. Karena token akses dikodekan ke dalam redirection URI, itu dapat diekspos ke pemilik sumber daya dan aplikasi lain yang berada di perangkat yang sama.

Jadi apa yang bisa kita pertimbangkan:

  1. Ini untuk OAuth publik yaitu ketika klien tidak perlu terdaftar dan tidak memiliki rahasia klien sendiri. Tapi apa server auth memeriksa url redirect dan ini sebenarnya cukup untuk keamanan.

  2. Token Access muncul di bilah alamat peramban sehingga pengguna dapat menyalin url dan mengirim ke orang lain dan itu juga akan dicatat sebagai pengguna, yaitu sesuatu seperti perbaikan Sesi. Tetapi browser membuat pengalihan tambahan dengan mengganti histori untuk menghapus fragmen hash dari url. Peretas juga dapat mencuri token akses dengan mengendus trafik HTTP tetapi ini dapat dengan mudah dilindungi oleh HTTPS. Beberapa ekstensi peramban jahat dapat memiliki akses ke url dari bilah alamat tetapi ini pada akhirnya merupakan situasi yang buruk seperti HTTPS cert yang rusak. Dan bahkan aliran kode Auth tidak dapat membantu di sini eter. Jadi yang bisa saya lihat adalah bahwa lewat token akses melalui potongan hash dari url benar-benar aman.

  3. Pemisahan token akses singkat dan token refresh tidak berguna ketika menggunakan HTTPS dan jujur ​​tidak begitu berguna bahkan pada HTTP mentah. Tetapi fakta bahwa klien melalui aliran implisit tidak dapat menerima token penyegaran juga tidak masuk akal.

Jadi saya pikir kita harus memperkenalkan aliran hibah baru "aman tersirat" yang bekerja secara ketat di https, memungkinkan token penyegaran (atau kita harus menyingkirkannya sama sekali), dan lebih disukai daripada aliran hibah Auth Cose

stokito
sumber
3

Bagi kami, klien kami ingin dapat mengotentikasi dengan aplikasi kami di ponsel mereka satu kali, dan tidak perlu masuk lagi selama berminggu-minggu pada suatu waktu. Dengan aliran kode, Anda mendapatkan token penyegaran bersama dengan token akses Anda. Aliran tersirat tidak memberikan Anda tanda penyegaran. Token akses memiliki kedaluwarsa yang relatif singkat, tetapi token penyegaran dapat memiliki hingga 90 hari. Setiap kali token akses kedaluwarsa, kode klien dan server dapat menggunakan token penyegaran untuk mendapatkan token akses baru plus token penyegaran, semuanya ada di belakang layar, tanpa campur tangan pengguna apa pun. Token penyegaran hanya dapat digunakan satu kali. Anda tidak dapat melakukan ini dengan Alur Tersirat. Jika Anda menggunakan Alur Tersirat, dan pengguna Anda tidak berinteraksi dengan aplikasi Anda selama lebih dari satu jam, mereka harus masuk lagi ketika mereka kembali. Itu tidak dapat diterima dalam kasus penggunaan kami,

Ini berfungsi dan aman karena token penyegaran dapat dicabut. Jika seorang pelanggan mengatakan bahwa mereka kehilangan ponsel atau laptop mereka atau seorang hacker masuk ke desktop mereka, kami dapat dengan mudah mencabut semua token penyegaran untuk pengguna tersebut. Selama seluruh proses, tidak ada Informasi Identifikasi Pribadi (PII) yang pernah menyentuh kode kami - yaitu kata sandi pengguna.

Aliran kode memang luar biasa, tetapi butuh lebih banyak pekerjaan. MS tidak memiliki perpustakaan Angular untuk menanganinya saat ini, jadi saya harus menulis satu. Jika Anda tertarik, saya dapat membantu Anda.

Tim Hardy
sumber
2

Jawaban saya adalah: Anda tidak dapat menerapkan aliran implisit dengan cara yang aman dan sederhana dengan server aplikasi web.

Proses otorisasi aplikasi web melibatkan interaksi pengguna sehingga Server Otentikasi harus mengarahkan kembali browser pengguna ke halaman target aplikasi web setelah otentikasi dan persetujuan pengguna (saya tidak melihat cara lain untuk mengirim pengguna kembali ke aplikasi web setelah beberapa interaksi dengan Server Otentikasi).

Jadi token harus diteruskan ke aplikasi web menggunakan URL pengalihan, kan?

Sebagaimana @NicolasGarnier menjelaskan dalam jawaban dan komentarnya, tidak ada cara untuk menyampaikan token sebagai fragmen URL - itu tidak akan mencapai server aplikasi web.

Dan memberikan token sebagai parameter URL dari redirect URL akan menjadi tidak aman bahkan di bawah HTTPS: jika halaman target (biarlah "halaman ucapan") berisi sumber daya (gambar, skrip, dll.) Sumber daya ini akan diperoleh oleh browser melalui seri permintaan HTTP (S) (masing-masing memiliki Refererheader HTTP yang berisi URL persis "halaman salam" termasuk parameter URL). Ini adalah cara token bisa bocor.

Jadi sepertinya tidak ada cara untuk meneruskan token di URL pengalihan. Itu sebabnya Anda memerlukan panggilan kedua (baik dari Server Otentikasi ke Klien (tetapi ke URL mana?) Atau dari Klien ke Server Otentikasi (panggilan kedua dalam aliran Kode Otorisasi))

Lu55
sumber