Pola Login API SISA

181

Saya membuat api REST, mengikuti saran apigee dengan seksama, menggunakan kata benda bukan kata kerja, versi api dimasukkan ke dalam url, dua jalur api per koleksi, DAPATKAN penggunaan POST PUT DELETE, dll.

Saya bekerja pada sistem login, tetapi tidak yakin tentang cara REST yang tepat untuk login pengguna. Saya tidak bekerja pada keamanan pada saat ini, hanya pola atau aliran login. (Nanti kita akan menambahkan 2 langkah oAuth, dengan HMAC, dll)

Opsi yang Mungkin

  • POST untuk sesuatu seperti https://api...com/v1/login.json
  • TETAP untuk sesuatu seperti https://api...com/v1/users.json
  • Sesuatu yang saya belum ...

Apa gaya REST yang tepat untuk login pengguna?

Scott Roepnack
sumber
9
Itu adalah format respons. .json memberi tahu server untuk merespons dengan json, .xml memberi tahu server untuk merespons dengan format xml. Alih-alih menjadikannya parameter opsional di belakang? blog.apigee.com/detail/…
Scott Roepnack
28
Belum pernah melihat negosiasi konten dilakukan di URL, hanya di tajuk. Di URL itu berarti Anda kehilangan manfaat caching dan banyak lagi.
Oded
10
@ScottRoepnack maka Anda harus mempertimbangkan Acceptheader HTTP.
Alessandro Vendruscolo
2
@Oded Jika Anda menggunakan Accepttajuk, Anda juga akan memiliki Vary: Accept, jadi caching tidak akan terpengaruh. Sambungan dalam ekstensi telah dibahas sebelumnya ; Saya setuju dengan jawaban Shonzilla di sana.
cmbuckley
2
@Daftar - saya tidak mengerti. mengapa Anda kehilangan manfaat caching jika Anda menentukan jenis konten dalam URL (baik sebagai akhiran .json ke jalur kueri atau sebagai tipe = parameter kueri json)? Dan siapa "kamu" dalam kasus ini? Siapa orang yang kehilangan manfaat caching? menurut saya hasil dari setiap kueri dapat di-cache tanpa memperhatikan apa yang ada di jalur kueri atau params.
Cheeso

Jawaban:

138

Desain Prinsip Arsitektur Web Modern oleh Roy T. Fielding dan Richard N. Taylor , yaitu urutan karya dari semua terminologi REST, berisi definisi interaksi klien-server:

Semua interaksi REST tidak memiliki kewarganegaraan . Artinya, setiap permintaan berisi semua informasi yang diperlukan agar konektor memahami permintaan, terlepas dari permintaan apa pun yang mungkin telah mendahuluinya .

Pembatasan ini menyelesaikan empat fungsi, 1 dan 3 penting dalam kasus khusus ini:

  • Pertama : menghapus segala kebutuhan konektor untuk mempertahankan status aplikasi di antara permintaan , sehingga mengurangi konsumsi sumber daya fisik dan meningkatkan skalabilitas;
  • 3 : memungkinkan perantara untuk melihat dan memahami permintaan secara terpisah , yang mungkin diperlukan ketika layanan disusun ulang secara dinamis;

Dan sekarang mari kita kembali ke kasus keamanan Anda. Setiap permintaan tunggal harus berisi semua informasi yang diperlukan, dan otorisasi / otentikasi tidak terkecuali. Bagaimana cara mencapai ini? Secara harfiah mengirim semua informasi yang diperlukan melalui kabel dengan setiap permintaan.

Salah satu contoh cara mengaktifkan ini adalah kode otentikasi pesan berbasis hash atau HMAC . Dalam praktiknya ini berarti menambahkan kode hash pesan saat ini ke setiap permintaan. Kode hash dihitung oleh fungsi hash kriptografi dikombinasikan dengan kunci kriptografi rahasia . Fungsi hash kriptografis dapat ditentukan sebelumnya atau bagian dari konsepsi REST kode-atas-permintaan (misalnya JavaScript). Kunci kriptografi rahasia harus disediakan oleh server ke klien sebagai sumber daya, dan klien menggunakannya untuk menghitung kode hash untuk setiap permintaan.

Ada banyak contoh implementasi HMAC , tetapi saya ingin Anda memperhatikan tiga berikut:

Cara kerjanya dalam praktik

Jika klien mengetahui kunci rahasia, maka siap untuk beroperasi dengan sumber daya. Kalau tidak, dia akan sementara dialihkan (kode status 307 Pengalihan Sementara) untuk mengotorisasi dan mendapatkan kunci rahasia, dan kemudian dialihkan kembali ke sumber asli. Dalam hal ini tidak perlu tahu sebelumnya (yaitu hardcode di suatu tempat) apa URL untuk mengotorisasi klien , dan mungkin untuk menyesuaikan skema ini dengan waktu.

Semoga ini bisa membantu Anda menemukan solusi yang tepat!

Akim
sumber
23
MAC dimaksudkan untuk membuktikan keaslian pesan dan melindungi dari gangguan dengan - tidak ada hubungannya dengan otentikasi pengguna
yrk
1
Menambahkan salah satu contoh, bagaimana menangani otentikasi pengguna / klien tanpa mengetahui " URL masuk " sebelumnya
Akim
Berikut adalah dua artikel bagus lainnya dengan contoh auth stateless untuk layanan REST: blog.jdriven.com/2014/10/… technicalrex.com/2015/02/20/…
Vladimir Rozhkov
41

TL; DR Login untuk setiap permintaan bukan komponen yang diperlukan untuk menerapkan keamanan API, otentikasi.

Sulit untuk menjawab pertanyaan Anda tentang login tanpa membicarakan keamanan secara umum. Dengan beberapa skema otentikasi, tidak ada login tradisional.

REST tidak menentukan aturan keamanan apa pun, tetapi implementasi yang paling umum dalam praktik adalah OAuth dengan otentikasi 3 arah (seperti yang telah Anda sebutkan dalam pertanyaan Anda). Tidak ada masuk per se, setidaknya tidak dengan setiap permintaan API. Dengan auth 3 arah, Anda hanya menggunakan token.

  1. Pengguna menyetujui klien API dan memberikan izin untuk mengajukan permintaan dalam bentuk token yang berumur panjang
  2. Klien Api memperoleh token berumur pendek dengan menggunakan token yang berumur panjang.
  3. Klien Api mengirimkan token berumur pendek dengan setiap permintaan.

Skema ini memberi pengguna opsi untuk mencabut akses kapan saja. Secara praktis semua RESTful APIs yang tersedia untuk umum yang pernah saya lihat menggunakan OAuth untuk mengimplementasikannya.

Saya hanya tidak berpikir Anda harus membingkai masalah Anda (dan pertanyaan) dalam hal login, melainkan berpikir tentang mengamankan API secara umum.

Untuk info lebih lanjut tentang otentikasi API REST secara umum, Anda dapat melihat sumber daya berikut:

Slavo
sumber
Ya, OAuth! Jawaban yang sangat mudah, harus menjadi jawaban yang diterima, imho.
Levite
26

Bagian besar dari filosofi REST adalah untuk mengeksploitasi sebanyak mungkin fitur standar dari protokol HTTP saat merancang API Anda. Menerapkan filosofi itu untuk otentikasi, klien dan server akan menggunakan fitur otentikasi HTTP standar di API.

Layar masuk bagus untuk kasus penggunaan pengguna manusia: kunjungi layar masuk, berikan pengguna / kata sandi, set cookie, klien menyediakan cookie itu dalam semua permintaan di masa mendatang. Manusia yang menggunakan browser web tidak dapat diharapkan untuk memberikan id dan kata sandi pengguna dengan setiap permintaan HTTP individu.

Tetapi untuk API REST, layar masuk dan cookie sesi tidak sepenuhnya diperlukan, karena setiap permintaan dapat menyertakan kredensial tanpa memengaruhi pengguna manusia; dan jika klien tidak bekerja sama kapan saja, 401respons "tidak sah" dapat diberikan. RFC 2617 menjelaskan dukungan otentikasi dalam HTTP.

TLS (HTTPS) juga akan menjadi pilihan, dan akan memungkinkan otentikasi klien ke server (dan sebaliknya) dalam setiap permintaan dengan memverifikasi kunci publik dari pihak lain. Selain itu ini mengamankan saluran untuk bonus. Tentu saja, pertukaran keypair sebelum komunikasi diperlukan untuk melakukan ini. (Catatan, ini khusus tentang mengidentifikasi / mengautentikasi pengguna dengan TLS. Mengamankan saluran dengan menggunakan TLS / Diffie-Hellman selalu merupakan ide yang baik, bahkan jika Anda tidak mengidentifikasi pengguna dengan kunci publiknya.)

Contoh: misalkan token OAuth adalah kredensial masuk lengkap Anda. Setelah klien memiliki token OAuth, itu dapat diberikan sebagai id pengguna dalam otentikasi HTTP standar dengan setiap permintaan. Server dapat memverifikasi token pada penggunaan pertama dan menyimpan hasil cek dengan waktu-to-live yang diperbarui dengan setiap permintaan. Setiap permintaan yang membutuhkan otentikasi dikembalikan 401jika tidak disediakan.

wberry
sumber
1
"karena setiap permintaan dapat menyertakan kredensial tanpa memengaruhi pengguna manusia" otentikasi 3-arah dan OAuth diciptakan karena hal dalam kutipan itu buruk. Jika Anda memberikan kredensial dengan setiap permintaan tanpa mekanisme pada server untuk mencabutnya, itu tidak aman jika digunakan tanpa SSL.
Slavo
1
Setiap kali ada konsep pengguna, sesuatu harus diteruskan dari klien ke server untuk mengidentifikasi pengguna mana. Token OAuth tentu dapat berfungsi sebagai "kredensial" di sini, alih-alih kombinasi pengguna / kata sandi yang sebenarnya. Mengamankan saluran dengan TLS tentu selalu merupakan hal yang baik, tetapi itu hampir tidak penting. Bahkan jika Anda menggunakan cookie, semacam token masih akan dikirim ke server dengan setiap permintaan, hanya dengan header cookie alih-alih header otentikasi.
wberry
Dan jika Anda tidak menggunakan TLS atau OAuth untuk alasan apa pun, apakah mengirim pengguna / kata sandi setiap kali benar-benar lebih buruk daripada mengirimnya sekali saja? Jika penyerang dapat memperoleh pengguna / kata sandi, penyerang kemungkinan juga dapat memperoleh cookie sesi.
wberry
Perbedaan antara cookie dan header otentikasi yang menjadi kredensial adalah bahwa cookie selalu dikaitkan dengan domain tertentu. Ini berarti bahwa ketika API menerima cookie, ia tahu dari mana asalnya (ditulis oleh domain yang sama sebelumnya). Dengan tajuk, Anda tidak pernah tahu dan Anda harus menerapkan pemeriksaan khusus untuk ini. Secara umum saya setuju, mereka berdua kredensial, tetapi saya pikir lulus kredensial tidak masuk. Login adalah tindakan aktif membuka pintu. Dalam kasus auth 3-way, hanya persetujuan pertama dari klien yang akan login.
Slavo