Bagaimana cara merancang otentikasi pengguna dari aplikasi klien?

14

Saya telah mengembangkan aplikasi yang akan mendukung banyak pengguna. Masalahnya adalah saya tidak bisa mencari tahu, bagaimana cara mengotentikasi klien / pengguna.

Saya membuat aplikasi seperti http://quickblox.com/ di mana saya akan memberikan kredensial kepada pengguna saya dan mereka akan menggunakannya untuk membangun aplikasi N di mana mereka tidak dapat memasukkan nama pengguna dan kata sandi untuk mendapatkan otentikasi.

Mari kita asumsikan itu sebagai berikut. (Sama seperti QuickBlox)

1. Pengguna membuat akun di situs web saya.
2. Pengguna dapat membuat kunci N API dan mengeluarkan kredensial. (Untuk beberapa aplikasi)
3. Pengguna akan menggunakan kredensial ini dalam aplikasi mereka (Android, iOS, Javascript dll ...) untuk berbicara dengan API REST saya.
(REST APIs memiliki akses baca dan tulis.)

Perhatian ku?

Pengguna akan memasukkan kredensial mereka (kunci API dan kunci sekresi) dalam aplikasi yang mereka bangun, bagaimana jika seseorang mendapatkan kunci ini dan mencoba meniru pengguna? (Dengan mendekompilasi APK atau langsung melihat ke dalam kode JavaScript.

Apakah saya salah di suatu tempat?
Saya bingung dengan arsitek mekanisme pengguna tiga tingkat ini.

Alok Patel
sumber
Hal yang tampaknya Anda coba lakukan tidak mungkin.
user253751
Ada banyak aplikasi di luar sana yang melakukan hal yang sama. Saya tidak yakin bagaimana mereka mengotentikasi pengguna.
Alok Patel
Apakah Anda mencoba mengotentikasi aplikasi klien , atau pengguna ? Banyak aplikasi mengautentikasi pengguna. Tak satu pun dari mereka mengautentikasi aplikasi klien dengan cara yang tidak bisa dipecahkan.
user253751
Ya oleh klien, maksud saya, saya ingin mengautentikasi pengguna saja.
Alok Patel
4
Oh, baik dalam sistem otentikasi yang paling umum, Anda hanya mendapatkan pengguna untuk memasukkan nama pengguna dan kata sandi mereka, dan mengirim mereka dengan aman ke server yang memeriksa mereka dan (dengan aman) mengembalikan token sesi, dan kemudian Anda mengirim token sesi di setiap permintaan di masa depan.
user253751

Jawaban:

7

Saya telah merancang API REST selama beberapa tahun terakhir. Anda terlalu khawatir. Baru-baru ini pengguna lain di forum ini telah mengajukan pertanyaan, di mana ia khawatir tentang menyimpan titik akhir URI dalam kode sisi klien JavaScript-nya .

Aturan yang sama berlaku untuk Anda sebagaimana berlaku untuk pengembang JavaScript. Jika Anda mengizinkan orang dari luar untuk mengintegrasikan API Anda, API Anda memiliki visibilitas yang sama dengan situs web biasa dan Anda harus memperlakukannya dengan cara yang sama.

Kutipan dari jawaban asli:

Ketika Anda membuat situs web dan Anda tidak ingin pengguna melakukan sesuatu, Anda tidak menerapkan fungsi itu atau melarang pengguna tertentu untuk menggunakannya. Dengan REST API yang seharusnya memiliki endpoint publik, itu hampir sama, Anda harus memperlakukannya seperti situs web publik.

API REST Anda harus cukup kuat untuk tidak memungkinkan operasi yang tidak valid, seperti akses ke data dari pengguna yang berbeda.

Anda harus mendesain token akses aplikasi Anda hanya untuk memungkinkan operasi yang Anda ingin diizinkan. Anda dapat memiliki dua jenis token akses:

  • master token : dapat digunakan oleh pembuat aplikasi dan menyediakan lebih banyak fungsi dari API Anda,
  • application token : token yang sebenarnya akan disimpan di dalam aplikasi dan hanya akan memiliki akses terbatas ke API Anda, hanya untuk operasi yang tidak dapat merusak data Anda atau aplikasi programmer.

Tapi apa yang seseorang mendekonstruksi kode sumber, mengeluarkan token dari aplikasi, mencari tahu apa titik akhir publik dan menyalahgunakan layanan web Anda?

Kecuali jika Anda secara langsung mengelola pengembangan aplikasi yang menggunakan API Anda, tidak ada yang benar-benar melarang orang menyalahgunakan API Anda dengan cara yang sama langsung dari aplikasi.

Andy
sumber
Penjelasan yang bagus sejauh ini, saya punya pertanyaan. Katakanlah salah satu API saya dibuat untuk mengambil semua data terkait (A + B) dari pengguna saya . Pengguna saya menggunakan API ini di aplikasinya untuk mendapatkan filtered data(B) dari penggunanya saja. Sekarang apakah mungkin, atau apakah ada solusi untuk mencegah pengguna ketiga mencuri semua data (A + B) dari pengguna saya . Apakah masuk akal?
Alok Patel
@ AlokPatel Tidak ada solusi lain untuk tidak mengimplementasikan fungsionalitas. Ketika Anda melakukannya, selalu ada risiko seseorang menipu hash identitasnya agar terlihat seperti orang lain. Secara terprogram masalah Anda tidak dapat diselesaikan. Seperti yang saya katakan, jika Anda tidak ingin menawarkan fungsionalitas, jangan terapkan. Karena aplikasi kemungkinan akan menyimpan hash login di dalamnya, setelah aplikasi dikerahkan, begitu juga kunci API Anda dan itu tidak tersedia untuk umum.
Andy
Terima kasih untuk penjelasannya. Jadi Apa yang saya dapatkan sejauh ini adalah REST APIs sama dengan situs web mana pun yang kami sebarluaskan situs web. Jika saya tidak ingin pengguna melakukan sesuatu maka saya tidak mengimplementasikannya di REST APIs saya. Jadi yang bisa saya lakukan adalah memiliki kunci terpisah untuk pustaka klien (Android, iOS, JS) yang dapat dikompromikan dengan lebih sedikit fungsionalitas dan kunci berbeda yang akan digunakan sisi server (PHP, Java, node.js) dengan fungsionalitas yang diperluas. Semoga ini berhasil!
Alok Patel
Bisakah Anda jelaskan poin ini untuk Anda? Kecuali jika Anda secara langsung mengelola pengembangan aplikasi yang menggunakan API Anda
Alok Patel
@AlokPatel Yang saya maksudkan adalah, saat ini Anda khawatir Anda memberi seseorang akses ke API, mereka mungkin mendistribusikan akses dan mulai menyalahgunakan API. Jika Anda tidak memiliki kendali atas pengembangan aplikasi yang menggunakan API Anda, mereka mungkin melakukan hal yang sama bahkan sendiri.
Andy
5

Masalah Anda bukan masalah teknis melainkan masalah bisnis.

Katakanlah Anda memiliki API Anda, yang Anda jual kepada pelanggan Anda (pengembang aplikasi) dengan tarif tetap sebesar £ 100 setahun, akses tanpa batas.

Kalau begitu jelas, saya dapat membeli layanan Anda dengan harga £ 100 dan menjualnya kepada 10 orang dengan harga masing-masing $ 50. Anda tidak menginginkan itu! jadi Anda mencoba memikirkan batasan yang akan memungkinkan Anda menjual API Anda tanpa terbuka untuk arbitrasi.

  • Jika Anda hanya membatasi jumlah Aplikasi, pelanggan dapat membuat satu aplikasi yang menerima koneksi dari aplikasi lain dan meneruskannya.

  • Jika Anda membatasi pengguna, sekali lagi, pelanggan dapat menyembunyikan pengguna di balik autentikasi sendiri dan tampaknya menjadi pengguna tunggal.

Yang perlu Anda lakukan adalah meneruskan biaya setiap panggilan API ke pelanggan Anda. yaitu biaya per panggilan API, atau tetapkan kuota panggilan per tahun.

Ini mendorong masalah arbitrase yang sama ke pelanggan Anda. Ini memaksa mereka untuk melakukan tindakan untuk mencegah pengguna mereka mencuri kunci mereka. Dalam hal ini, sembunyikan api Anda di belakang api yang diautentikasi oleh pengguna mereka sendiri.

Ewan
sumber
Saya sudah merencanakan untuk membatasi penggunaan API saya berdasarkan jumlah panggilan API sehingga masalah terkait bisnis bukan urusan saya saat ini, saya hanya khawatir tentang kunci yang dicuri.
Alok Patel
Dari sudut pandang bisnis, masalahnya tidak terpecahkan. Sayangnya, Anda tidak dapat menyelesaikannya secara terprogram.
Andy
1
Proble bisnis. Diselesaikan dengan menagih per panggilan. Jika kuncinya dicuri, pelanggan Anda akan kalah. Bukan kamu. Berikan pelanggan Anda cara untuk membatalkan kunci curian dan katakan terserah mereka untuk memiliki api perantara untuk mencegah penyalahgunaan
Ewan
2

Jawaban lain semua tampaknya menunjukkan bahwa masalah menyimpan rahasia di aplikasi pada perangkat konsumen tidak dapat dipecahkan.

Tentu saja.

Dua prinsip (detail implementasi akan mengikuti):

  1. Titik akhir autentikasi yang sebenarnya harus terbuka secara anonim untuk umum.
  2. Server entah bagaimana harus terlibat dalam mengautentikasi klien dan menyediakan kunci API.

Mengingat bahwa, jika klien membuat permintaan ke titik akhir otentikasi dengan kredensial, dan server mengautentikasi, server dapat menghasilkan token sementara dinamis (sementara artinya berbasis waktu). Token ini harus diingat dalam klien dan dikirim dengan permintaan berikutnya.

Anda akan membutuhkan mekanisme untuk "menyegarkan" token secara berkala, artinya, mendapatkan yang baru. Cukup buat titik akhir REST yang memungkinkan untuk menghasilkan token baru dari yang sudah ada, untuk menghindari keharusan mengautentikasi ulang dari kredensial.

Jika Anda mencoba untuk menghindari pengguna akhir mengautentikasi ulang diri mereka sendiri, maka otentikasi ini dapat menjadi pengaturan satu kali awal di aplikasi saat terinstal.

Solusi ini hanya menghindari kebutuhan untuk menyimpan token statis yang tertanam dalam biner aplikasi. Token dibuat on-the-fly oleh server hanya sebagai tanggapan atas otentikasi yang berhasil. Untuk pengguna jahat untuk memeriksa aplikasi Anda dan mencoba untuk mendapatkan akses API yang tidak sah, mereka masih perlu mengautentikasi sama seperti orang lain.

Brandon
sumber
Solusi menarik, meskipun sebagian besar bergantung pada bagaimana klien OP akan membuat kode aplikasi mereka. Ini mengatakan, pendekatan yang diusulkan dapat memungkinkan untuk kemudian menyimpan sisi server kunci API dan setelah otentikasi yang berhasil dari pengguna mereka sendiri dapat meneruskan kunci sementara untuk aplikasi yang sebenarnya untuk digunakan. dengan cara ini tidak ada yang disimpan di aplikasi itu sendiri.
Newtopian
Itu berlaku untuk semua API. Jika konsumen API tidak mengkonsumsinya dengan benar, hal-hal mungkin tidak berfungsi. Ini harus menjadi bagian terdokumentasi dari API.
Brandon
Ngomong-ngomong, ada standar untuk membantu mempermudah ini, seperti OAuth.
Brandon
0

Jika Anda memiliki kunci unik per-aplikasi, Anda bisa menggunakannya hanya selama otentikasi koneksi awal, yang diprakarsai oleh klien, setelah itu Anda beralih ke token otentikasi unik per aplikasi yang bergulir.

Server Anda mengubah (menggulung) token untuk setiap aplikasi klien dari waktu ke waktu (misalnya ditambah / dikurangi beberapa penundaan fuzzy / acak acak, misalnya). Rolling token hanya diketahui antara oleh server dan klien yang diautentikasi.

Token baru dikembalikan dengan piggy pada balasan reguler. Setiap kali balasan berisi token baru, aplikasi penerima perlu beralih untuk menggunakannya dalam permintaan berikutnya.

Setiap kali pertukaran dengan klien keluar dari sinkronisasi (beberapa jenis kesalahan protokol) server Anda akan meminta otentikasi ulang (melalui balasan kesalahan untuk permintaan klien berikutnya, atau didukung oleh piggy pada respons yang valid terhadap permintaan klien, untuk contoh).

Otentikasi awal yang diprakarsai oleh klien sementara token bergulir aktif digunakan harus dianggap dengan kecurigaan - itu bisa menjadi upaya meniru. Saya hanya akan mengizinkannya jika pertukaran tidak digunakan untuk interval yang lebih lama dari yang diharapkan, yang dapat, misalnya, disebabkan oleh pemadaman klien / restart dengan contoh baru yang tidak memiliki token bergulir.

Akan lebih baik untuk mempertahankan token di sisi klien sehingga klien yang memulai kembali dapat melanjutkan dari tempat pendahulunya pergi - secara signifikan mempersempit celah untuk meniru.

Skema semacam itu akan membuat peniruan setidaknya cukup sulit - klien peniruan harus memprediksi dengan tepat jendela ketika klien yang berwenang berhenti mengirim permintaan cukup lama bagi server untuk memutuskan tidak apa-apa untuk menerima otentikasi klien baru dengan kunci yang ditentukan dapat terjadi. Permintaan seperti itu di luar jendela yang diizinkan dapat digunakan sebagai deteksi upaya meniru dan mungkin memulai beberapa tindakan pencegahan (daftar hitam IP, dll.).

Dan Cornilescu
sumber
0

Dari apa yang saya tahu, apa yang Anda sebutkan adalah satu-satunya cara untuk melakukan ini. Aplikasi menyimpan kunci jelas merupakan risiko, tetapi ada berbagai cara untuk menghindarinya. Anda selalu dapat menggunakan keystore untuk menyimpan kunci, daripada hardcoding, sehingga memaksa login satu kali.

Juga, Anda harus mempertimbangkan untuk mengikat kunci ke klien, sehingga, jika seseorang meniru, Anda harus memiliki lapisan keamanan untuk memeriksa klien, kunci dan agen pengguna untuk memblokir permintaan segera. Miliki use case untuk menerbitkan kembali atau memastikan kembali bahwa kunci tidak ditiru.

Arun
sumber
Apa yang dikerjakan untuk JavaScript? Bagaimana cara arsiteknya?
Alok Patel
Saya berasumsi Anda berbicara tentang membuat aplikasi hybrid. Jika begitu, maka Anda pasti bisa membuat plugin untuk menyimpan kunci. Jika Anda akan meng-host aplikasi dan berbicara tentang solusi web seluler, maka pikirkan tentang merender halaman menggunakan wadah dan Anda dapat mengandalkan token sesi yang disarankan sebelumnya
Arun
Tidak, bukan itu masalahnya. Saya akan menjadi penyedia API teratas ketiga, pengguna saya akan menggunakan layanan API saya di aplikasi mereka. Itu bisa Android, iOS, JavaScript dll ...
Alok Patel
0

Jika Anda bergantung pada pemberian token otorisasi kepada pelanggan Anda untuk dimasukkan ke dalam aplikasi mereka, akan selalu memungkinkan secara teoritis bagi seseorang untuk merekayasa balik aplikasi dan mengekstraknya. Untuk mencegahnya, Anda memerlukan mekanisme yang tidak memerlukan rahasia di dalam aplikasi klien. Itu rumit. Saya dapat menyarankan beberapa opsi untuk Anda pikirkan.

Anda memiliki masalah setelah memberikan kredensial, Anda tidak memiliki kendali atas seberapa aman mereka disimpan. Juga, jika Anda meminta pengguna untuk mengirimkan kredensial kepada Anda, maka seseorang dapat MITM koneksi Anda dan mencuri token secara langsung tanpa repot-repot merekayasa balik aplikasi.

Salah satu cara untuk membuatnya lebih sulit untuk mengekstrak token otorisasi Anda adalah mengaburkannya. Ini hanya meningkatkan standar, tetapi tidak membuatnya mustahil, dan untuk melakukan itu Anda harus tetap memegang kendali atas rahasia tersebut. Anda dapat menerapkan perpustakaan yang berisi informasi rahasia dan khusus untuk setiap pelanggan. Anda dapat menggunakan perpustakaan untuk berkomunikasi dengan server Anda dan Anda bahkan mungkin tidak perlu memberi tahu informasi rahasia kepada pengguna Anda, itu bisa saja tertanam di perpustakaan. Ini tidak memecahkan masalah seseorang membalikkan rekayasa perpustakaan Anda, tetapi itu membuat Anda mengendalikan tingkat kebingungan. Kekurangannya adalah begitu satu orang telah memecahkan kebingungan di perpustakaan, mereka dapat menyerang perpustakaan Anda, kecuali jika Anda menulis kode yang membuat setiap perpustakaan berbeda secara signifikan. Itu memperkenalkan serangkaian masalahnya sendiri.

Ini mungkin sedikit menyimpang dari ruang lingkup pertanyaan Anda, tetapi ini terkait dengan keamanan token Anda, jadi saya akan menyebutkannya. Untuk mencegah pencurian kecil dari token melalui kabel, Anda mungkin tidak ingin mengirim token secara langsung, sebagai gantinya Anda bisa menandatangani lalu lintas menggunakan fungsi HMAC. Anda dapat memeriksa validitas pesan dengan menghitung HMAC dari pesan di server dan membandingkannya dengan HMAC yang dikirim dari klien. Anda akan menggunakan token sebagai kunci untuk fungsi HMAC sehingga hanya seseorang yang mengetahui token yang dapat menandatangani lalu lintas. Ini lebih baik untuk keamanan token Anda karena Anda tidak pernah mengirimnya langsung ke server sehingga tidak dapat dicegat dan dicuri secara langsung. Untuk informasi lebih lanjut tentang HMACS, lihat pertanyaan ini: /security/20129/how-and-when-do-i-use-hmac/20301

Tidak ada solusi keamanan yang tidak dapat ditembus, Anda harus memutuskan berapa biaya yang harus Anda tanggung vs kemungkinan dan biaya untuk dikompromikan.

ThePragmatist
sumber
Saya tidak bisa membuat perpustakaan dan menaruh rahasia di dalamnya, itu akan berbeda untuk setiap pengguna saya.
Alok Patel
Untuk memperjelas, saya menyarankan Anda bisa membangun perpustakaan khusus untuk setiap pengguna Anda dan menyembunyikan rahasia masing-masing di dalam perpustakaan. Anda perlu menulis sebuah sistem untuk menghasilkan pustaka secara otomatis sesuai permintaan untuk setiap pengguna baru yang mungkin lebih banyak pekerjaan daripada yang ingin Anda lakukan.
ThePragmatist
0

Mengutip diri sendiri:

Saya tidak dapat menemukan, bagaimana cara mengotentikasi klien / pengguna ... di mana mereka tidak dapat memasukkan nama pengguna dan kata sandi mereka untuk mendapatkan otentikasi.

Nah, itu sedikit kontradiksi, bukan? ;)

Seperti yang orang lain katakan, Anda tidak bisa. Jika suatu Aplikasi menggunakan kunci API, seseorang dapat mendekompilasinya seperti yang Anda katakan untuk mendapatkan kunci dan menggunakannya juga.

Selain membutuhkan otentikasi pengguna yang tepat tambahan, Anda hanya dapat membatasi kerusakan:

  • daftar putih / daftar hitam IP
  • pelambatan
  • deteksi "aktivitas tidak biasa" dan sumbernya
  • pembaruan kunci mudah
dagnelies
sumber