Saya telah membaca di REST dan ada banyak pertanyaan tentang SO, serta di banyak situs dan blog lain. Meskipun saya belum pernah melihat pertanyaan spesifik ini ditanyakan ... untuk beberapa alasan, saya tidak dapat memahami konsep ini ...
Jika saya membuat RESTful API, dan saya ingin mengamankannya, salah satu metode yang saya lihat adalah menggunakan token keamanan. Ketika saya menggunakan API lain, ada token dan rahasia bersama ... masuk akal. Apa yang saya tidak mengerti adalah, permintaan untuk operasi layanan istirahat dilakukan melalui javascript (XHR / Ajax), apa untuk mencegah seseorang mengendusnya dengan sesuatu yang sederhana seperti FireBug (atau "lihat sumber" di browser) dan menyalin kunci API, lalu meniru identitas orang itu menggunakan kunci dan rahasia?
Jawaban:
api rahasia tidak diteruskan secara eksplisit, rahasia digunakan untuk menghasilkan tanda permintaan saat ini, di sisi server, server menghasilkan tanda mengikuti proses yang sama, jika dua tanda cocok, maka permintaan berhasil diautentikasi - jadi hanya tanda melewati permintaan, bukan rahasia.
sumber
Kami mengungkap API yang hanya dapat digunakan mitra di domain yang mereka daftarkan dengan kami. Isinya sebagian untuk publik (tetapi sebaiknya hanya ditampilkan di domain yang kami ketahui), tetapi sebagian besar bersifat pribadi bagi pengguna kami. Begitu:
Untuk menentukan apa yang ditampilkan, pengguna kami harus masuk dengan kami, tetapi ini ditangani secara terpisah.
Untuk menentukan di mana data ditampilkan, kunci API publik digunakan untuk membatasi akses ke domain yang kita ketahui, dan yang terpenting untuk memastikan data pengguna pribadi tidak rentan terhadap CSRF .
Kunci API ini memang terlihat oleh siapa pun, kami tidak mengautentikasi mitra kami dengan cara lain, dan kami tidak memerlukan REFERER . Tetap saja, ini aman:
Saat kami
get-csrf-token.js?apiKey=abc123
diminta:Cari kunci
abc123
di database dan dapatkan daftar domain yang valid untuk kunci itu.Cari cookie validasi CSRF. Jika tidak ada, buat nilai acak yang aman dan masukkan ke dalam cookie sesi khusus HTTP . Jika cookie memang ada, dapatkan nilai acak yang ada.
Buat token CSRF dari kunci API dan nilai acak dari cookie, dan tanda tangani . (Daripada menyimpan daftar token di server, kami menandatangani nilainya. Kedua nilai akan dapat dibaca dalam token yang ditandatangani, itu bagus.)
Setel tanggapan agar tidak di-cache, tambahkan cookie, dan kembalikan skrip seperti:
Catatan:
Hal di atas tidak mencegah skrip sisi server memalsukan permintaan, tetapi hanya memastikan bahwa domain tersebut cocok jika diminta oleh browser.
The kebijakan asal yang sama untuk JavaScript memastikan bahwa browser tidak dapat menggunakan XHR (Ajax) untuk memuat dan kemudian memeriksa sumber JavaScript. Sebaliknya, browser biasa hanya dapat memuatnya menggunakan
<script src="https://our-api.com/get-csrf-token.js?apiKey=abc123">
(atau yang setara dinamis), dan kemudian akan menjalankan kode tersebut. Tentu saja, server Anda tidak boleh mendukung Cross-Origin Resource Sharing atau JSONP untuk JavaScript yang dihasilkan.Sebuah skrip browser dapat mengubah nilai
document.domain
sebelum memuat skrip di atas. Tetapi kebijakan asal yang sama hanya memungkinkan untuk memperpendek domain dengan menghapus prefiks, seperti menulis ulangsubdomain.example.com
ke hanyaexample.com
, ataumyblog.wordpress.com
kewordpress.com
, atau di beberapa browser bahkanbbc.co.uk
keco.uk
.Jika file JavaScript diambil menggunakan beberapa skrip sisi server maka server juga akan mendapatkan cookie. Namun, server pihak ketiga tidak dapat membuat browser pengguna mengaitkan cookie itu ke domain kami. Karenanya, token CSRF dan cookie validasi yang telah diambil menggunakan skrip sisi server, hanya dapat digunakan oleh panggilan sisi server berikutnya, bukan di browser. Namun, panggilan sisi server tersebut tidak akan pernah menyertakan cookie pengguna, dan karenanya hanya dapat mengambil data publik. Ini adalah data yang sama yang dapat dikikis oleh skrip sisi server dari situs web mitra secara langsung.
Saat pengguna masuk, setel beberapa cookie pengguna dengan cara apa pun yang Anda suka. (Pengguna mungkin sudah masuk sebelum JavaScript diminta.)
Semua permintaan API berikutnya ke server (termasuk permintaan GET dan JSONP) harus menyertakan token CSRF, cookie validasi CSRF, dan (jika masuk) cookie pengguna. Server sekarang dapat menentukan apakah permintaan tersebut dapat dipercaya:
Kehadiran token CSRF yang valid memastikan JavaScript dimuat dari domain yang diharapkan, jika dimuat oleh browser.
Kehadiran token CSRF tanpa cookie validasi menunjukkan adanya pemalsuan.
Kehadiran token CSRF dan cookie validasi CSRF tidak memastikan apa pun: ini bisa berupa permintaan sisi server palsu, atau permintaan valid dari browser. (Tidak boleh merupakan permintaan dari browser yang dibuat dari domain yang tidak didukung.)
Kehadiran cookie pengguna memastikan pengguna masuk, tetapi tidak memastikan pengguna adalah anggota dari mitra yang diberikan, atau bahwa pengguna melihat situs web yang benar.
Kehadiran cookie pengguna tanpa cookie validasi CSRF menunjukkan adanya pemalsuan.
Kehadiran cookie pengguna memastikan permintaan saat ini dibuat melalui browser. (Dengan asumsi pengguna tidak akan memasukkan kredensial mereka di situs web yang tidak dikenal, dan dengan asumsi kami tidak peduli tentang pengguna yang menggunakan kredensial mereka sendiri untuk membuat beberapa permintaan sisi server.) Jika kami juga memiliki cookie validasi CSRF, maka cookie validasi CSRF itu adalah juga diterima menggunakan browser. Selanjutnya, jika kita juga memiliki token CSRF dengan tanda tangan yang valid, dannomor acak dalam cookie validasi CSRF cocok dengan yang ada di token CSRF itu, kemudian JavaScript untuk token itu juga diterima selama permintaan yang sama sebelumnya saat cookie CSRF ditetapkan, karenanya juga menggunakan browser. Ini kemudian juga menyiratkan kode JavaScript di atas dijalankan sebelum token disetel, dan pada saat itu domain tersebut valid untuk kunci API yang diberikan.
Jadi: server sekarang dapat dengan aman menggunakan kunci API dari token yang ditandatangani.
Jika suatu saat server tidak mempercayai permintaan tersebut, maka 403 Forbidden akan dikembalikan. Widget dapat meresponsnya dengan menampilkan peringatan kepada pengguna.
Tidak perlu menandatangani cookie validasi CSRF, karena kami membandingkannya dengan token CSRF yang ditandatangani. Tidak menandatangani cookie membuat setiap permintaan HTTP lebih pendek, dan validasi server sedikit lebih cepat.
Token CSRF yang dihasilkan berlaku tanpa batas waktu, tetapi hanya dalam kombinasi dengan cookie validasi, sangat efektif hingga browser ditutup.
Kami dapat membatasi masa tanda tangan token. Kami dapat menghapus cookie validasi CSRF saat pengguna logout, untuk memenuhi rekomendasi OWASP . Dan untuk tidak membagikan nomor acak per pengguna di antara beberapa mitra, seseorang dapat menambahkan kunci API ke nama cookie. Tetapi meskipun demikian seseorang tidak dapat dengan mudah menyegarkan cookie validasi CSRF ketika token baru diminta, karena pengguna mungkin menjelajahi situs yang sama di beberapa jendela, berbagi satu cookie (yang, saat menyegarkan, akan diperbarui di semua jendela, setelah itu Token JavaScript di jendela lain tidak lagi cocok dengan cookie tunggal itu).
Bagi mereka yang menggunakan OAuth, lihat juga OAuth dan Widget Sisi Klien , dari mana saya mendapatkan ide JavaScript. Untuk penggunaan API di sisi server , di mana kami tidak dapat mengandalkan kode JavaScript untuk membatasi domain, kami menggunakan kunci rahasia alih-alih kunci API publik.
sumber
OPTIONS
permintaan yang dilakukan sebelumnya dengan beberapa kunci API publik di URL, server mungkin memberi tahu browser domain mana yang diizinkan (atau membatalkan permintaan). Berhati-hatilah karena beberapa permintaan tidak memerlukan permintaan pra-penerbangan, atau tidak akan menggunakan CORS sama sekali , dan CORS memerlukan IE8 +. Jika beberapa pengganti Flash digunakan untuk IE7, mungkin beberapa dinamikacrossdomain.xml
dapat membantu mencapai hal yang sama untuk itu. Kami belum mencoba CORS / Flash.Pertanyaan ini memiliki jawaban yang diterima tetapi hanya untuk memperjelas, otentikasi rahasia bersama berfungsi seperti ini:
sumber
Saya kira yang Anda maksud adalah kunci sesi, bukan kunci API. Masalah itu diwarisi dari protokol http dan dikenal sebagai Session hijacking . "Solusi" yang normal adalah, seperti di situs web manapun, mengubah ke https.
Untuk menjalankan layanan REST aman Anda harus mengaktifkan https, dan mungkin otentikasi klien. Tapi bagaimanapun, ini di luar ide REST. REST tidak pernah berbicara tentang keamanan.
sumber
Apa yang ingin Anda lakukan di sisi server adalah menghasilkan id sesi kedaluwarsa yang dikirim kembali ke klien saat login atau signup. Klien kemudian dapat menggunakan id sesi itu sebagai rahasia bersama untuk menandatangani permintaan berikutnya.
ID sesi hanya dilewatkan satu kali dan ini HARUS melalui SSL.
Lihat contoh di sini
Gunakan nonce dan stempel waktu saat menandatangani permintaan untuk mencegah pembajakan sesi.
sumber
Saya akan mencoba menjawab pertanyaan tersebut dalam konteks aslinya. Jadi pertanyaannya adalah "Apakah kunci rahasia (API) aman untuk ditempatkan dalam JavaScript.
Menurut pendapat saya, ini sangat tidak aman karena mengalahkan tujuan otentikasi antar sistem. Karena kunci akan diekspos ke pengguna, pengguna dapat mengambil informasi yang tidak diizinkan. Karena pada umumnya otentikasi komunikasi istirahat hanya berdasarkan pada API Key.
Solusi menurut saya adalah bahwa panggilan JavaScript pada dasarnya meneruskan permintaan ke komponen server internal yang bertanggung jawab untuk melakukan panggilan istirahat. Komponen server internal katakanlah Servlet akan membaca kunci API dari sumber yang aman seperti sistem file berbasis izin, memasukkan ke header HTTP dan membuat panggilan istirahat eksternal.
Saya harap ini membantu.
sumber