Membuat API untuk aplikasi seluler - Otentikasi dan Otorisasi

189

Gambaran

Saya ingin membuat API (REST) ​​untuk aplikasi saya. Tujuan awal / utama adalah untuk konsumsi oleh aplikasi seluler (iPhone, Android, Symbian, dll). Saya telah mencari mekanisme berbeda untuk otentikasi dan otorisasi untuk API berbasis web (dengan mempelajari implementasi lainnya). Kepalaku terlilit sebagian besar konsep dasar tetapi saya masih mencari bimbingan di beberapa bidang. Hal terakhir yang ingin saya lakukan adalah menemukan kembali roda, tetapi saya tidak menemukan solusi standar yang sesuai dengan kriteria saya (namun kriteria saya salah kaprah, jadi jangan ragu untuk mengkritiknya juga). Selain itu, saya ingin API sama untuk semua platform / aplikasi yang menggunakannya.

o Ya

Saya akan melanjutkan dan membuang keberatan saya untuk oAuth karena saya tahu itu akan menjadi solusi pertama yang ditawarkan. Untuk aplikasi seluler (atau lebih khusus aplikasi non-web), sepertinya salah meninggalkan aplikasi (pergi ke browser web) untuk otentikasi. Selain itu, tidak ada cara (saya tahu) untuk browser untuk mengembalikan panggilan balik ke aplikasi (terutama lintas platform). Saya tahu beberapa aplikasi yang melakukan itu, tetapi hanya terasa salah dan memberikan istirahat pada aplikasi UX.

Persyaratan

  1. Pengguna memasukkan nama pengguna / kata sandi ke dalam aplikasi.
  2. Setiap panggilan API diidentifikasi oleh aplikasi panggilan.
  3. Overhead dijaga agar tetap minimum dan aspek authtif intuitif untuk pengembang.
  4. Mekanisme ini aman untuk pengguna akhir (kredensial login mereka tidak diekspos) maupun pengembang (kredensial aplikasi mereka tidak diekspos).
  5. Jika memungkinkan, tidak memerlukan https (tidak berarti persyaratan sulit).

Pikiran Saya Saat Ini tentang Implementasi

Pengembang eksternal akan meminta akun API. Mereka akan menerima apikey dan apisecret. Setiap permintaan akan membutuhkan minimal tiga parameter.

  • apikey - diberikan kepada pengembang saat pendaftaran
  • timestamp - berfungsi sebagai pengidentifikasi unik untuk setiap pesan untuk apikey yang diberikan
  • hash - hash cap waktu + apisecret

Apikey diperlukan untuk mengidentifikasi aplikasi yang mengeluarkan permintaan. Timestamp bertindak serupa dengan oauth_nonce dan menghindari / mengurangi serangan replay. Hash memastikan bahwa permintaan benar-benar dikeluarkan dari pemilik apikey yang diberikan.

Untuk permintaan terotentikasi (yang dilakukan atas nama pengguna), saya masih ragu-ragu antara pergi dengan rute access_token atau kombo hash nama pengguna dan kata sandi. Apa pun itu, pada suatu titik suatu kombo nama pengguna / kata sandi akan diperlukan. Jadi ketika itu terjadi, hash dari beberapa bagian informasi (apikey, apisecret, timestamp) + kata sandi akan digunakan. Saya suka umpan balik tentang aspek ini. FYI, mereka harus memilah password terlebih dahulu, karena saya tidak menyimpan kata sandi di sistem saya tanpa hashing.

Kesimpulan

FYI, ini bukan permintaan untuk bagaimana membangun / menyusun API secara umum hanya bagaimana menangani otentikasi dan otorisasi hanya dari dalam suatu aplikasi.

Pikiran Acak / Pertanyaan Bonus

Untuk API yang hanya memerlukan apikey sebagai bagian dari permintaan, bagaimana Anda mencegah orang lain selain pemilik apikey untuk dapat melihat apikey (sejak dikirim di tempat yang jelas) dan membuat permintaan berlebihan untuk mendorong mereka melewati batas penggunaan? Mungkin saya hanya memikirkan hal ini, tetapi tidakkah seharusnya ada sesuatu untuk mengotentikasi bahwa permintaan telah diverifikasi kepada pemilik yang benar? Dalam kasus saya, itulah tujuan dari apisecret, tidak pernah ditampilkan / ditransmisikan tanpa hash.

Berbicara tentang hash, bagaimana dengan MD5 vs hmac-sha1? Apakah itu benar-benar penting ketika semua nilai hash dengan data yang cukup panjang (mis. Apisecret)?

Saya sebelumnya telah mempertimbangkan untuk menambahkan garam per pengguna / baris ke hash kata sandi pengguna saya. Jika saya melakukan itu, bagaimana mungkin aplikasi dapat membuat hash yang cocok tanpa mengetahui garam yang digunakan?

jsuggs
sumber
1
Berharap mendapatkan beberapa komentar / saran lagi. Apakah pertanyaannya terlalu kabur / ambigu?
jsuggs
6
pertanyaannya sempurna tetapi, bahkan hampir 2 tahun kemudian, implementasi oauth tampaknya misterius ... saya mengalami kesulitan mencapai apa yang telah Anda bahas di atas. saya memiliki dimensi tambahan: saya tidak ingin menggunakan pasangan loginName / kata sandi - saya ingin menggunakan verifikasi identitas google di android / ios (symbian dinyatakan oleh WWF sebagai "spesies yang hampir punah") dan saya menolak untuk mengembangkan windows mobile (apa pun mereka menyebutnya hari ini).
tony gil
8
itu konyol bahwa sebanyak semua orang menyarankan oauth 2.0 ive belum menemukan tutorial yang jelas, sederhana atau contoh yang menggunakan bahasa Inggris umum untuk menjelaskan langkah-langkah, persyaratan, lakukan dan tidak
boleh
2
Baca di aliran spesifik OAuth2.0 ini (Alur Kata Sandi Pemilik Sumber Daya). Tidak ada pengalihan ke situs web. techblog.hybris.com/2012/06/11/...
Franklin
1
Saya juga mencari jawaban yang sama. Saya menemukan artikel bagus yang ditulis baru-baru ini. Saya harap ini membantu. stormpath.com/blog/the-ultimate-guide-to-mobile-api-security
Baru di Rails

Jawaban:

44

Cara saya berpikir untuk melakukan bagian login ini di proyek saya adalah:

  1. sebelum login, pengguna meminta login_tokendari server. Ini dihasilkan dan disimpan di server berdasarkan permintaan, dan mungkin memiliki masa hidup yang terbatas.

  2. untuk masuk aplikasi menghitung hash kata sandi pengguna, lalu hash kata sandi dengan login_tokenuntuk mendapatkan nilai, mereka kemudian mengembalikan login_tokenhash gabungan dan.

  3. Server memeriksa login_tokenapakah ia telah dihasilkan, menghapusnya dari daftar login_tokens yang valid . Server kemudian menggabungkan hash yang tersimpan dari kata sandi pengguna dengan login_tokendan memastikan bahwa itu cocok dengan token gabungan yang dikirimkan. Jika cocok, Anda telah mengautentikasi pengguna Anda.

Keuntungan dari ini adalah bahwa Anda tidak pernah menyimpan kata sandi pengguna di server, kata sandi tidak pernah lulus dengan jelas, kata sandi hash hanya diteruskan secara jelas pada pembuatan akun (meskipun mungkin ada cara-cara di sekitar ini), dan harus aman dari serangan replay karena login_tokendihapus dari DB yang digunakan.

Michael Anderson
sumber
Terima kasih, saya lupa menambahkan bagian tentang hashing kata sandi di sisi aplikasi. Saya tidak menyimpan kata sandi pengguna saya di tempat yang jelas (saya hash sebelum menyimpan).
jsuggs
2
Saya melihat kelemahan dari metode ini: Anda tidak dapat menyimpan kata sandi yang asin di DB. Jika penyerang meletakkan tangan mereka di DB Anda, mereka tidak perlu melakukan dekripsi. Karena kata sandi hash adalah kata sandi asli dalam skema ini.
sigod
2
@sigod Anda benar. Meskipun saya pikir ada dikotomi mendasar di sana - Anda harus memercayai transportasi Anda, atau Anda perlu memercayai penyimpanan Anda. Sistem login yang menggunakan kata sandi asin mempercayai lapisan transport - dan dengan demikian meneruskan kata sandi dari pengguna ke sistem autentikasi secara jelas. Kasus ini tidak mempercayai lapisan transport (saya pikir ini karena platform yang saya targetkan memiliki dukungan buruk untuk SHTTP). Jika Anda mempercayai lapisan transpor, Anda mungkin dapat melakukan trade-off lainnya.
Michael Anderson
Saya memiliki 3 masalah: 1) bagaimana kata sandi pengguna tidak pernah disimpan di server? pada langkah 2 Anda menyebutkan bahwa itu menyimpan kata sandi pengguna hash. 2) Kata sandi pengguna tidak pernah diberikan secara jelas. Tapi itu sebenarnya hash pada klien dan kemudian dibandingkan dengan kata sandi hash di server, yang hampir sama dengan melewati dan menyimpannya dengan jelas, apa gunanya melakukan itu? 3) Metode ini mengasumsikan penyerang tidak tahu bagaimana login_token + kata sandi di-hash, yang melanggar prinsip Kerckhoffs dan membuatnya benar-benar tidak aman.
Tamer Shlash
14

Itu banyak sekali pertanyaan dalam satu, saya kira beberapa orang tidak berhasil membaca sampai akhir :)

Pengalaman saya tentang otentikasi layanan web adalah bahwa orang biasanya overengineer, dan masalahnya hanya sama seperti yang Anda temui di halaman web. Kemungkinan opsi yang sangat sederhana akan mencakup https untuk langkah login, mengembalikan token, mengharuskannya untuk disertakan dengan permintaan di masa depan. Anda juga bisa menggunakan autentikasi dasar http, dan hanya meneruskan barang di header. Untuk keamanan tambahan, putar / kedaluwarsa token sering, periksa permintaan berasal dari blok IP yang sama (ini bisa berantakan meskipun pengguna seluler bergerak antar sel), digabungkan dengan kunci API atau serupa. Sebagai alternatif, lakukan langkah "kunci permintaan" pada oauth (seseorang telah menyarankan ini di jawaban sebelumnya dan ini merupakan ide yang baik) sebelum mengautentikasi pengguna, dan menggunakannya sebagai kunci yang diperlukan untuk menghasilkan token akses.

Alternatif yang belum saya gunakan tetapi saya telah mendengar banyak tentang sebagai alternatif yang ramah perangkat untuk oAuth adalah xAuth . Lihat itu dan jika Anda menggunakannya maka saya akan sangat tertarik untuk mendengar apa kesan Anda.

Untuk hashing, sha1 sedikit lebih baik tetapi jangan menutupinya - apa pun perangkat dapat dengan mudah (dan dengan cepat dalam arti kinerja) implementasi mungkin baik-baik saja.

Semoga itu bisa membantu, semoga berhasil :)

Lorna Mitchell
sumber
Terima kasih atas tanggapannya. Saya telah mencari xAuth dan itu bisa menjadi rute yang saya gunakan sehingga saya bisa berakhir dengan instalasi oAuth, yang membuat proses yang lebih standar untuk berinteraksi dengan API.
jsuggs
9

Jadi yang Anda cari adalah semacam mekanisme otentikasi sisi server yang akan menangani aspek otentikasi dan otorisasi aplikasi seluler?

Dengan asumsi inilah masalahnya, maka saya akan mendekatinya sebagai berikut (tetapi hanya karena saya adalah pengembang Java sehingga seorang C # guy akan melakukannya secara berbeda):

Layanan otentikasi dan otorisasi yang tenang

  1. Ini hanya akan berfungsi pada HTTPS untuk mencegah penyadapan.
  2. Ini akan didasarkan pada kombinasi RESTEasy , Spring Security dan CAS (untuk sistem masuk tunggal di beberapa aplikasi).
  3. Ini akan bekerja dengan browser dan aplikasi klien yang mendukung web
  4. Akan ada antarmuka manajemen akun berbasis web untuk memungkinkan pengguna mengedit detail mereka, dan admin (untuk aplikasi tertentu) untuk mengubah tingkat otorisasi

Pustaka / aplikasi keamanan sisi klien

  1. Untuk setiap platform yang didukung (mis. Symbian, Android, iOS dll) buat implementasi yang sesuai dari perpustakaan keamanan dalam bahasa asli platform (misalnya Java, ObjectiveC, C dll)
  2. Perpustakaan harus mengelola formasi permintaan HTTPS menggunakan API yang tersedia untuk platform yang diberikan (mis. Java menggunakan URLConnection dll)
  3. Konsumen dari perpustakaan otentikasi dan otorisasi umum (karena hanya itu saja) akan kode ke antarmuka tertentu dan tidak akan senang jika itu pernah berubah jadi pastikan itu sangat fleksibel. Ikuti pilihan desain yang ada seperti Spring Security.

Jadi sekarang setelah melihat dari 30.000 kaki selesai bagaimana Anda melakukannya? Yah, tidak sulit untuk membuat sistem otentikasi dan otorisasi berdasarkan teknologi yang terdaftar di sisi server dengan klien browser. Dalam kombinasi dengan HTTPS, kerangka kerja akan memberikan proses yang aman berdasarkan token bersama (biasanya disajikan sebagai cookie) yang dihasilkan oleh proses otentikasi dan digunakan setiap kali pengguna ingin melakukan sesuatu. Token ini disajikan oleh klien ke server setiap kali ada permintaan.

Dalam hal aplikasi seluler lokal, tampaknya Anda mencari solusi yang melakukan hal berikut:

  1. Aplikasi klien memiliki Daftar Kontrol Akses (ACL) yang ditentukan untuk mengontrol akses runtime ke panggilan metode. Misalnya, pengguna yang diberikan dapat membaca koleksi dari suatu metode, tetapi ACL mereka hanya mengizinkan akses ke objek yang memiliki Q di namanya sehingga beberapa data dalam koleksi cukup menarik oleh pencegat keamanan. Di Jawa ini sangat mudah, Anda cukup menggunakan anotasi Spring Security pada kode panggilan dan menerapkan proses respons ACL yang sesuai. Dalam bahasa lain, Anda sendirian dan mungkin perlu memberikan kode keamanan boilerplate yang memanggil ke perpustakaan keamanan Anda. Jika bahasa mendukung AOP (Pemrograman Berorientasi Aspek) maka gunakan sepenuhnya untuk situasi ini.
  2. Pustaka keamanan menyimpan daftar otorisasi lengkap ke dalam memori pribadi untuk aplikasi saat ini sehingga tidak harus tetap terhubung. Bergantung pada panjang sesi login, ini bisa menjadi operasi satu kali yang tidak pernah diulang.

Apa pun yang Anda lakukan, jangan mencoba untuk menciptakan protokol keamanan Anda sendiri , atau gunakan keamanan dengan ketidakjelasan. Anda tidak akan pernah bisa menulis algoritma yang lebih baik untuk ini daripada yang saat ini tersedia dan gratis. Juga, orang mempercayai algoritma terkenal. Jadi jika Anda mengatakan bahwa perpustakaan keamanan Anda memberikan otorisasi dan otentikasi untuk aplikasi seluler lokal menggunakan kombinasi SSL, HTTPS, SpringSecurity dan token terenkripsi AES maka Anda akan segera memiliki kredibilitas di pasar.

Semoga ini bisa membantu, dan semoga sukses dengan usaha Anda. Jika Anda ingin info lebih lanjut, beri tahu saya - Saya telah menulis beberapa aplikasi web berdasarkan Spring Security, ACL, dan sejenisnya.

Gary Rowe
sumber
Terima kasih info bagus Beberapa pertanyaan. Pertama, jika menguping dapat diterima (tidak yakin apakah itu / tidak, aplikasi saya dalam pikiran tidak memiliki informasi pribadi / berharga nyata, tetapi jika itu rasional saya akan berubah) maka apakah HTTPS sebenarnya diperlukan?
jsuggs
Anda dapat mengoperasikan keseluruhan sistem di luar HTTPS jika Anda mau. HTTPS hanya untuk melindungi informasi rahasia, jadi saya berasumsi bahwa selama fase otentikasi Anda akan melakukannya melalui HTTPS untuk memberikan jaminan bahwa nama pengguna / kata sandi / rahasia Anda dirahasiakan. Setelah token diserahkan dalam respons maka permintaan lebih lanjut dapat dibuat dengan jelas jika informasi yang terkandung dalam arus (yang diperlukan untuk mendapatkan otentikasi) tidak memerlukan perlindungan dari penyadap.
Gary Rowe
Juga, uraian protokol otentikasi CAS ini mungkin berguna: jasig.org/cas/protocol
Gary Rowe
9

Twitter membahas masalah aplikasi eksternal di oAuth dengan mendukung varian yang mereka sebut xAuth . Sayangnya sudah ada banyak skema lain dengan nama ini sehingga bisa membingungkan untuk memilah.

Protokolnya adalah oAuth, kecuali ia melompati fase token permintaan dan langsung mengeluarkan pasangan token akses setelah menerima nama pengguna dan kata sandi. (Mulai dari langkah E di sini .) Permintaan dan respons awal ini harus diamankan- mengirim nama pengguna dan kata sandi dalam plaintext dan menerima kembali token akses dan token rahasia. Setelah pasangan token akses telah dikonfigurasi, apakah pertukaran token awal adalah melalui model oAuth atau model xAuth tidak relevan bagi klien dan server selama sisa sesi. Ini memiliki keuntungan bahwa Anda dapat memanfaatkan infrastruktur oAuth yang ada dan memiliki implementasi yang hampir sama untuk aplikasi seluler / web / desktop. Kerugian utama adalah aplikasi diberikan akses ke nama pengguna dan kata sandi klien, tetapi tampaknya persyaratan Anda mengharuskan pendekatan ini.

Bagaimanapun, saya ingin setuju dengan intuisi Anda dan beberapa penjawab lain di sini: jangan mencoba untuk membangun sesuatu yang baru dari awal. Protokol keamanan bisa mudah dimulai tetapi selalu sulit dilakukan dengan baik, dan semakin berbelit-belit, semakin kecil kemungkinan pengembang pihak ketiga Anda dapat menerapkannya. Protokol hipotetis Anda sangat mirip dengan o (x) Auth - api_key / api_secret, nonce, sha1 hashing - tetapi alih-alih dapat menggunakan salah satu dari banyak perpustakaan yang ada, pengembang Anda perlu menggulirkannya sendiri.

lantius
sumber
2
Saya juga harus menunjukkan bahwa sepertinya titik akhir 'lewati permintaan token' akan berada di oAuth 2, itu tercantum dalam konsep saat ini sebagai jenis hibah akses "kata sandi". Lihat bagian 4.1.2: tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.2
lantius
Seperti yang saya sebutkan kepada Lonra, saya melihat lebih dalam pada xAuth dan secara khusus untuk alasan yang Anda sebutkan di akhir ... pengembang dapatkah Anda "meninggalkan rak" oAuth tools / libs untuk berinteraksi dengan API saya, yang merupakan "hal yang baik" .
jsuggs
6

Sangat terlambat ke pesta tetapi saya ingin memberikan beberapa poin tambahan untuk dipertimbangkan bagi siapa saja yang tertarik dengan masalah ini. Saya bekerja untuk perusahaan yang melakukan solusi keamanan API seluler ( approov ) sehingga seluruh area ini jelas relevan dengan minat saya.

Untuk mulai dengan, hal paling penting untuk dipertimbangkan ketika mencoba untuk mengamankan API seluler adalah berapa nilainya bagi Anda . Solusi yang tepat untuk bank berbeda dengan solusi yang tepat untuk seseorang yang hanya melakukan hal-hal untuk bersenang-senang.

Dalam solusi yang diusulkan Anda menyebutkan bahwa minimal tiga parameter akan diperlukan:

  • apikey - diberikan kepada pengembang saat pendaftaran
  • timestamp - berfungsi sebagai pengidentifikasi unik untuk setiap pesan untuk apikey yang diberikan
  • hash - hash cap waktu + apisecret

Implikasinya adalah bahwa untuk beberapa panggilan API tidak diperlukan nama pengguna / kata sandi. Ini dapat berguna untuk aplikasi di mana Anda tidak ingin memaksakan login (misalnya, menelusuri di toko online).

Ini adalah masalah yang sedikit berbeda dengan otentikasi pengguna dan lebih seperti otentikasi atau pengesahan perangkat lunak. Tidak ada pengguna, tetapi Anda masih ingin memastikan bahwa tidak ada akses jahat ke API Anda. Jadi, Anda menggunakan rahasia API Anda untuk menandatangani lalu lintas dan mengidentifikasi kode yang mengakses API sebagai asli. Masalah potensial dengan solusi ini adalah bahwa Anda kemudian harus memberikan rahasia di dalam setiap versi aplikasi. Jika seseorang dapat mengekstrak rahasia mereka dapat menggunakan API Anda, menyamar sebagai perangkat lunak Anda tetapi melakukan apa pun yang mereka suka.

Untuk mengatasi ancaman itu ada banyak hal yang dapat Anda lakukan tergantung pada seberapa berharganya data tersebut. Kebingungan adalah cara sederhana untuk membuatnya lebih sulit untuk mengekstrak rahasianya. Ada alat yang akan melakukannya untuk Anda, lebih untuk Android, tetapi Anda masih harus memiliki kode yang menghasilkan hash Anda dan individu yang cukup terampil selalu dapat memanggil fungsi yang melakukan hashing secara langsung.

Cara lain untuk mengurangi penggunaan berlebihan API yang tidak memerlukan login adalah dengan membatasi lalu lintas dan berpotensi mengidentifikasi dan memblokir alamat IP yang dicurigai. Jumlah upaya yang ingin Anda lakukan akan sangat tergantung pada seberapa berharga data Anda.

Di luar itu, Anda dapat dengan mudah mulai masuk ke domain pekerjaan harian saya. Bagaimanapun, ini adalah aspek lain dari pengamanan API yang menurut saya penting dan ingin ditandai.

ThePragmatist
sumber