REST API untuk situs web yang menggunakan Facebook untuk otentikasi

86

Kami memiliki situs web di mana satu - satunya cara untuk masuk dan mengautentikasi diri Anda dengan situs tersebut adalah dengan Facebook (ini bukan pilihan saya). Pertama kali Anda masuk dengan Facebook, akun dibuat secara otomatis untuk Anda.

Kami sekarang ingin membuat aplikasi iPhone untuk situs kami dan juga API publik untuk orang lain menggunakan layanan kami.

Pertanyaan ini tentang bagaimana mengotentikasi dengan situs web kami dari aplikasi / API dan dipecah menjadi 2 bagian:

  1. Apa cara yang benar untuk menangani otentikasi REST dari API ke situs web yang hanya menggunakan Facebook OAuth sebagai metode otentikasi?

Saya telah membaca dan meneliti banyak tentang metode standar otentikasi untuk REST API. Kami tidak dapat menggunakan metode seperti Basic Auth melalui HTTPS , karena tidak ada kredensial untuk pengguna tersebut. Sesuatu seperti ini tampaknya hanya untuk mengautentikasi aplikasi menggunakan API.

Saat ini, cara terbaik yang dapat saya pikirkan adalah Anda mencapai / mengotorisasi titik akhir di API kami, mengalihkan ke Facebook OAuth, kemudian mengarahkan kembali ke situs dan memberikan 'token' yang dapat digunakan oleh pengguna API untuk mengautentikasi selanjutnya. permintaan.

  1. Untuk aplikasi resmi yang kami buat, kami tidak perlu menggunakan API publik dengan cara yang sama. Lalu, apa cara terbaik untuk berbicara dengan situs web kami dan mengautentikasi pengguna?

Saya memahami (menurut saya) cara mengautentikasi aplikasi pihak ketiga yang menggunakan API kami, menggunakan kunci API (publik) dan kunci rahasia (pribadi). Namun, ketika harus mengautentikasi pengguna yang menggunakan aplikasi, saya agak bingung tentang bagaimana cara melakukannya ketika satu-satunya cara kami harus mengautentikasi pengguna adalah Facebook.

Saya merasa seperti saya kehilangan sesuatu yang sangat jelas, atau tidak sepenuhnya memahami cara kerja REST API publik, jadi saran dan bantuan apa pun akan sangat kami hargai.

Adam
sumber
Saya memiliki pertanyaan serupa di stackoverflow.com/questions/30230482/… yang membahas beberapa di antaranya
JVK

Jawaban:

99

UPDATE: lihat di bawah

Saya telah berpikir keras tentang pertanyaan ini juga. Belum sepenuhnya jelas bagi saya, tetapi inilah rute yang ingin saya tuju. Saya membuat REST API dan hanya pengguna saya yang diautentikasi dengan Facebook connect.

Di KLIEN:

  1. Gunakan API Facebook untuk masuk dan mendapatkan kode OAUTH2.
  2. Tukarkan kode ini dengan token akses.
  3. Dalam setiap panggilan ke API khusus saya, saya akan menyertakan id pengguna Facebook dan token akses.

Di API (untuk setiap metode yang membutuhkan otentikasi pengguna):

  1. Buat permintaan ke grafik / me Facebook menggunakan token akses dari atas.
  2. Verifikasi bahwa id pengguna Facebook yang dikembalikan cocok dengan id pengguna yang diteruskan ke API saya dari atas.
  3. Jika token akses telah kedaluwarsa, komunikasi tambahan diperlukan.

Saya belum menguji ini. Bagaimana bunyinya?

--- Update: 27 Juli 2014 untuk menjawab pertanyaan ---

Saya hanya menggunakan pertukaran di atas satu kali saat login. Setelah saya menentukan pengguna mana yang masuk, saya membuat token akses saya sendiri, dan token itu digunakan sejak saat itu. Jadi aliran baru terlihat seperti ini ...

Di KLIEN:

  1. Gunakan API Facebook untuk masuk dan mendapatkan kode OAUTH2.
  2. Tukarkan kode ini dengan token akses.
  3. Minta token akses dari API saya , termasuk token Facebook sebagai parameter

Di API

  1. Terima permintaan token akses.
  2. Buat permintaan ke grafik / me Facebook menggunakan token akses facebook
  3. Verifikasi bahwa pengguna Facebook ada dan cocok dengan pengguna di database saya
  4. Buat token akses saya sendiri, simpan, dan kembalikan ke klien untuk digunakan mulai saat ini
Chris Greenwood
sumber
Hei, itu semacam balasan yang terlambat, tetapi solusi Anda tampaknya memperbaiki masalah yang saya alami di jawaban pertama saya. Tentu saja Anda harus menggunakan HTTPS agar tidak mengirim pasangan (id, token) pada kabel dalam teks yang jelas. Tapi sepertinya itu harus berhasil!
Olivier Lance
Saya pikir ada baiknya menelepon / saya di server dan membuat token akses Anda sendiri, yang akan digunakan oleh klien seluler.
Der_Meister
Saya menemukan bahwa menyimpan rahasia FB di aplikasi seluler adalah praktik yang buruk. Facebook menyarankan untuk menyimpannya di server Anda saja. developers.facebook.com/docs/opengraph/using-actions/…
Der_Meister
Jika kita mengirim user_id dan access_token ke server API setiap saat (sebagai post / get params). Apakah akan menciptakan lubang keamanan jika seseorang dapat mencegat koneksi?
Nathan Do
@NathanDo Gunakan HTTPS antara klien Anda dan server API dan seharusnya tidak menjadi masalah jika seseorang menyadap koneksi (selain kerentanan tipe Heartbleed).
dcr
15

Ini adalah implementasi saya menggunakan JWTs (JSON Web Tokens), pada dasarnya mirip dengan jawaban terbaru Chris. Saya telah menggunakan Facebook JS SDK dan JWT.

Inilah implementasi saya.

  1. Klien: Gunakan Facebook JS SDK untuk masuk dan mendapatkan token akses.

  2. Klien: Minta JWT dari API saya dengan memanggil /verify-access-tokentitik akhir.

  3. MyAPI: Menerima token akses, verifikasi dengan memanggil /metitik akhir API Facebook.

  4. MyAPI: Jika token akses valid, temukan pengguna dari database, masukkan pengguna jika ada. Buat JWT dengan bidang wajib sebagai muatan, tetapkan masa berlaku, tanda tangani dengan kunci rahasia dan kirim kembali ke klien.

  5. Klien: Menyimpan JWT di penyimpanan lokal.

  6. Klien: Mengirim token (JWT dari langkah 5) bersama dengan permintaan untuk panggilan API berikutnya.

  7. MyAPI: validasi token dengan kunci rahasia, jika token valid, tukarkan token dengan yang baru, kirim kembali ke klien bersama dengan respons API. (Tidak ada panggilan API eksternal untuk verifikasi token di sini setelahnya) [jika token tidak valid / kadaluwarsa, minta klien untuk mengautentikasi lagi dan ulangi dari 1]

  8. Klien Mengganti token yang disimpan dengan yang baru dan menggunakannya untuk panggilan API berikutnya. Setelah masa berlaku token terpenuhi, token kedaluwarsa mencabut akses ke API.

Setiap token digunakan sekali.

Baca lebih banyak jawaban tentang keamanan dan JWT

Seberapa aman JWT

Jika Anda dapat memecahkan kode JWT, bagaimana mereka aman?

JSON Web Tokens (JWT) sebagai identifikasi pengguna dan token otentikasi

Semua Vаиітy
sumber
3
Saya kira # 3 seharusnya /debug_tokenbegitu, jadi Anda dapat memeriksa bahwa token sebenarnya untuk aplikasi Anda.
Peppe LG
2
Jangan meminta access_tokendi Klien. Gunakan "alur kerja kode". Lulus codeuntuk MyAPI dan membuat perjalanan lain bulat untuk Facebook untuk pertukaran codedengan access_token. Ini dijelaskan lebih menyeluruh di sini: developers.facebook.com/docs/facebook-login/security
omikron
5

Saya mencoba menjawab pertanyaan yang sama dan telah melalui banyak bacaan akhir-akhir ini ...

Saya tidak akan memiliki "jawaban" tetapi hal-hal menjadi sedikit lebih jelas bagi saya. Sudahkah Anda membaca komentar di artikel yang Anda sebutkan ? Saya menemukan mereka sangat menarik dan bermanfaat.

Akibatnya, dan mengingat bagaimana hal-hal telah berkembang sejak artikel pertama ditulis, inilah yang menurut saya akan saya lakukan:

  • HTTPS di mana-mana - ini memungkinkan Anda melupakan HMAC, penandatanganan, nonce, ...

  • Gunakan OAuth2:

    • Ketika permintaan otentikasi datang dari aplikasi / situs web saya sendiri, gunakan 'trik' ini (atau variasinya) yang dijelaskan dalam balasan artikel yang disebutkan sebelumnya.

    • Dalam kasus saya, saya memiliki dua jenis pengguna: mereka yang memiliki kredensial masuk / sandi klasik dan mereka yang telah mendaftar dengan Facebook Connect.
      Jadi saya akan memberikan formulir login biasa dengan tombol "Masuk dengan Facebook". Jika pengguna masuk dengan kredensial "klasik", saya hanya akan mengirimkannya ke titik akhir OAuth2 saya dengan grant_type=password.
      Jika dia memilih untuk masuk melalui Facebook, menurut saya itu akan menjadi proses dua langkah:

      • Pertama, gunakan Facebook iOS SDK untuk membuka FBSession
      • Setelah selesai dan aplikasi diberikan kontrol kembali, seharusnya ada cara untuk mendapatkan ID Facebook untuk pengguna tersebut. Saya akan mengirim ID ini sendiri ke titik akhir OAuth2 saya dengan pemberian ekstensi yang dipahami oleh server saya sebagai "menggunakan ID Pengguna FB".

Harap dicatat bahwa saya masih meneliti semua hal ini, jadi itu mungkin bukan jawaban yang sempurna ... bahkan mungkin bukan jawaban yang benar! Tapi saya pikir itu akan menjadi titik awal yang baik. Gagasan menggunakan "hibah ekstensi" untuk otentikasi Facebook mungkin melibatkan keharusan mendaftarkannya untuk melakukan sesuatu dengan benar? Saya tidak begitu yakin.

Bagaimanapun, saya harap saya dapat membantu Anda sedikit, dan setidaknya itu dapat memulai diskusi untuk menemukan solusi terbaik untuk masalah ini :)

Perbarui
Login Facebook bukanlah solusi seperti yang ditunjukkan dalam komentar: siapa pun dapat mengirim ID pengguna sewenang-wenang dan masuk sebagai pengguna ini di API.

Bagaimana melakukannya seperti ini:

  • Tampilkan formulir login dengan tombol "login Facebook"
  • Jika metode login ini dipilih, bertindak seperti Facebook SDK: buka halaman web dari server otentikasi Anda, yang akan memulai login Facebook.
  • Setelah pengguna masuk, Facebook akan menggunakan URL pengalihan Anda untuk mengonfirmasi; buat URL tersebut mengarah ke titik akhir lain dari server autentikasi Anda (mungkin dengan parameter tambahan yang menunjukkan bahwa panggilan tersebut berasal dari aplikasi?)
  • Ketika titik akhir otentikasi tercapai, otentikasi dapat dengan aman mengidentifikasi pengguna, mempertahankan ID Pengguna FB / Sesi FB dan mengembalikan token akses ke aplikasi Anda menggunakan skema URL khusus, seperti yang akan dilakukan Facebook SDK

Terlihat lebih baik?

Olivier Lance
sumber
1
Terimakasih atas balasan anda! Saya telah memikirkan sebagian besar dari apa yang Anda katakan tetapi perhatian utama yang saya miliki dengan menggunakan FB iOS SDK dan kemudian mengirim ID Pengguna Facebook adalah bukankah mudah untuk mengirim ID apa pun yang Anda inginkan ke titik akhir API Anda dan mengklaimnya. pengguna lain? Di sinilah saya biasanya akhirnya terjebak ..
Adam
Memang! Aku bodoh karena tidak memikirkannya ... Jadi solusinya harus melalui server otentikasi Anda sendiri entah bagaimana ...
Olivier Lance
Saya telah memperbarui jawaban saya dengan ide solusi lain ... tetapi baru menyadari bahwa Anda telah menyebutkannya dalam pertanyaan awal Anda! Saya tidak bisa melihat yang lain saat ini ...
Olivier Lance