Otentikasi berbasis token menggunakan akses dan menyegarkan token

8

Saya menerapkan sistem otentikasi berbasis token untuk REST API menggunakan token akses berumur pendek dan token refresh yang berumur panjang. Ini adalah ikhtisar abstrak dari titik akhir API yang relevan (HTTPS diberlakukan untuk semua titik akhir):

Titik akhir:

POST /register/
POST /login/
POST /logout/
POST /password/change/

Penerapan:

POST /register/:

  • Permintaan: Klien mengirim nama pengguna, email, dan kata sandi di JSON.
  • Tindakan server:
    1. Memvalidasi input, membuat pengguna dalam basis data (menyimpan id pengguna, nama pengguna, email, dan kata sandi hash).
    2. Membuat token akses berumur pendek dalam format JWT (berisi id pengguna, tanggal yang dikeluarkan, dan tanggal kedaluwarsa).
    3. Membuat token penyegaran berumur panjang sebagai string UUID dan menyimpannya dalam basis data (menyimpan id pengguna dan menyegarkan token).
  • Respons: Server mengembalikan token akses dan menyegarkan token di JSON.

POST /login/:

  • Permintaan: Klien mengirim nama pengguna dan kata sandi di JSON.
  • Tindakan server:
    1. Memvalidasi input, memeriksa apakah kredensial valid dengan memeriksa database.
    2. Jika kredensial valid, buat token akses berumur pendek dan refresh token berumur panjang seperti yang disebutkan sebelumnya.
  • Respons: Sama seperti /register/, mengembalikan token akses dan menyegarkan token di JSON.

POST /logout/:

  • Permintaan: Klien mengirimkan token penyegaran di Authorizationheader sebagai Bearertoken.
  • Tindakan server:
    1. Memvalidasi token penyegaran dengan memeriksa basis data penyegaran token.
    2. Menghapus token penyegaran dari database.
      Catatan: Ini membuat token akses valid, tetapi karena akan berumur pendek (1 jam atau lebih, saya pikir itu akan baik-baik saja).
  • Respons: Mengembalikan apakah permintaan logout berhasil diproses di JSON.

POST /password/change/:

  • Permintaan: Klien mengirimkan token akses di Authorizationheader sebagai Bearertoken, dan juga mengirimkan kata sandi lama dan kata sandi baru di JSON melalui HTTPS.
  • Tindakan server:
    1. Mendekode token akses untuk mengambil pengguna, dan memeriksa kata sandi lama pengguna dengan database.
    2. Menyetel hash kata sandi pengguna dalam database ke hash kata sandi baru.
    3. Menghapus semua token penyegaran yang terkait dengan pengguna di basis data token penyegaran untuk dasarnya log out sesi yang ada (meninggalkan token akses berumur pendek).
  • Respons: Mengembalikan apakah permintaan perubahan kata sandi berhasil diproses di JSON.

Pertanyaan:

  1. Apakah pendekatan ini aman? Secara khusus:
    • Apakah mengirim nama pengguna dan kata sandi melalui JSON aman jika dilakukan melalui HTTPS? Bagaimana saya mencegah domain tidak sah melakukan panggilan ke titik akhir ini? Selanjutnya, bagaimana saya mencegah login terprogram?
    • Haruskah token penyegaran di-hash sebelum menyimpannya dalam database, atau apakah saya hanya paranoid?
  2. Jika klien adalah browser web, bagaimana cara saya menyimpan token refresh dengan aman pada klien?
    • Satu ide yang saya miliki untuk menyimpan token refresh adalah: ketika pengguna login, selain mengirim token refresh ke klien, server menyimpan token dalam HttpOnlycookie dengan securebendera. Otorisasi masih akan dilakukan melalui Authorizationtajuk, tetapi ketika klien pada awalnya memuat, itu dapat mengirim GETpermintaan ke titik akhir yang memeriksa apakah cookie berisi token penyegaran yang valid, dan jika demikian, kembalikan ke pengguna di JSON. Dengan kata lain, satu-satunya waktu cookie akan benar-benar digunakan adalah mengembalikan token refresh di dalam cookie kepada klien. Apakah pendekatan ini aman? Saya pikir itu akan mencegah CSRF karena tidak ada efek samping ketika meminta token penyegaran dari cookie, tetapi apakah ada cara lain penyerang bisa mencegat token penyegaran (dengan asumsi HTTPS)?
Kootling
sumber
2
Mengapa tidak menggunakan Open ID Connect daripada mencoba menerapkan mekanisme keamanan logon Anda sendiri?
Erik Eidt
Saya tidak ingin harus menangani server tambahan untuk bertindak sebagai penyedia koneksi OpenID. Juga, saya lebih suka memiliki kontrol penuh atas aliran otentikasi sehingga saya dapat dengan mudah menentukan bug dan kerentanan keamanan.
Kootling
2
Saya tidak berpikir itu memerlukan server tambahan jika Anda hanya menggunakannya. Juga, melakukan implementasi Anda sendiri dengan protokol Anda sendiri memiliki risiko keamanan sendiri mungkin lebih dari menggunakan pendekatan standar yang muncul, tetapi siapa yang tahu pasti?
Erik Eidt

Jawaban:

2

Apakah pendekatan ini aman? Secara khusus:

  • Apakah mengirim nama pengguna dan kata sandi melalui JSON aman jika dilakukan melalui HTTPS?

Iya. Header, params permintaan, dan badan permintaan dienkripsi selama komunikasi.

Begitu berada di sisi server, jangan login badan permintaan :-)

  • Bagaimana saya mencegah domain tidak sah melakukan panggilan ke titik akhir ini?

Kamu tidak bisa. Pada dasarnya, begitu API ada di WWW, itu secara otomatis terkena semua jenis kedengkian. Yang terbaik yang bisa Anda lakukan adalah bersiap-siap dan waspada terhadap ancaman. Setidaknya tentang hal-hal yang menjadi perhatian Anda. Coba lihat di sini .

Pendekatan yang mungkin untuk masalah tersebut dapat menerapkan (atau membuat kontrak) seorang Manajer API .

Manajer API On-premise dapat mengurangi permukaan serangan karena semua titik akhir di belakang AM belum tentu publik.

Anda dapat mencapai hasil yang sama dengan beberapa produk di cloud, tetapi mereka bukan kepalang mahal untuk arus utama.

Bagaimanapun, titik akhir Manajemen API akan tetap terkena serangan.

  • Selanjutnya, bagaimana saya mencegah login terprogram?

Jika dengan login terprogram yang Anda maksud adalah serangan dengan kekerasan, ambang (jumlah maksimum permintaan yang diizinkan per detik) dan daftar hitam harus cukup untuk mencegah desakan penyerang. Untuk informasi lebih lanjut, lihat di sini .

Banyak Manajer API menyediakan di luar kotak Konfigurasi Batas API dan Daftar Putih .

Jika Anda terbiasa dengan Google API Console, maka Anda dapat menebak apa yang bisa dilakukan oleh Manajer API.

  • Haruskah token penyegaran di-hash sebelum menyimpannya dalam database, atau apakah saya hanya paranoid?

Apakah token penyegaran adalah UUID biasa atau apa pun, saya tidak suka mengekspos detail implementasi semacam ini. Jadi saya akan menyarankan untuk hash. Bagi saya, semakin buram detail implementasi dari lapisan keamanan, semakin baik.

Mengenai keamanan JWT, lihat di sini .

  • Jika klien adalah browser web, bagaimana cara saya menyimpan token refresh dengan aman pada klien?

Anda mungkin tertarik dengan JSON Web Token (JWT) - Penyimpanan di sisi klien .

Laiv
sumber
Mengenai login terprogram, saya ingin mencegah seseorang membuat front-end mereka sendiri ke API (meskipun seperti yang Anda katakan ini praktis tidak mungkin). Juga, token penyegaran (yang merupakan UUIDs, bukan JWTs) saat ini disimpan sebagai plaintext dalam database, jadi saya pasti harus hash mereka, kan? Mengenai penyimpanan token sisi klien, saya ingin menyimpan token penyegaran dan bertahan di seluruh sesi, jadi sessionStoragetidak akan berfungsi. Juga, localStoragedan document.cookietampaknya tidak aman karena mereka dapat diakses oleh JavaScript. Apakah pendekatan saya masuk akal, atau berpotensi tidak aman?
Kootling
1. Ya, saya akan menyimpan tohed token alih-alih teks biasa. Hanya untuk membuat konten tabel buram ke proses lain. 2. Jika saya harus memilih antara Penyimpanan lokal dan cookie, saya memilih cookie. Meskipun demikian, saya akan melakukan sedikit riset terlebih dahulu tentang kerentanannya. Juga, pertimbangkan untuk menambah keamanan suatu mekanik untuk membatalkan token secara manual.
Laiv
Dengan "cookie," maksud Anda document.cookieatau cookie HttpOnly dengan bendera aman, mirip dengan pendekatan yang saya sebutkan di atas?
Kootling
HttpHanya dan amankan flag tidak mencegah Anda dari XST dan XSRF. Tapi itu membuat cookie aman untuk serangan XSS, yang saya anggap dasar. So Yes, HttpOnly dan amankan flag. Ingatlah bahwa Anda tidak akan memiliki akses ke cookie dari Javascript
Laiv
Bagaimanapun, saya mendorong Anda untuk checkout perbedaan proyek OWASP terkait dengan aplikasi Web, API, REST dan JWT. Anda akan menemukan lebih banyak info daripada yang saya bisa berikan di sini.
Laiv