Menangani perpanjangan / sesi token kadaluwarsa dalam RESTful API

17

Saya sedang membangun API yang tenang yang menggunakan token JWT untuk otentikasi pengguna (dikeluarkan oleh logintitik akhir dan mengirim semua header setelah itu), dan token harus di-refresh setelah jumlah waktu yang tetap (menggunakan renewtitik akhir, yang mengembalikan token yang diperbarui ).

Mungkin saja sesi API pengguna menjadi tidak valid sebelum token berakhir, karenanya semua titik akhir saya mulai dengan memeriksa bahwa: 1) token masih valid dan 2) sesi pengguna masih valid. Tidak ada cara untuk membatalkan token secara langsung, karena klien menyimpannya secara lokal.

Oleh karena itu, semua titik akhir saya harus memberi sinyal kepada klien saya tentang dua kondisi yang mungkin: 1) bahwa sudah waktunya untuk memperbarui token atau 2) bahwa sesi menjadi tidak valid, dan mereka tidak lagi diizinkan untuk mengakses sistem. Saya dapat memikirkan dua alternatif untuk titik akhir saya untuk memberi sinyal kepada klien mereka ketika salah satu dari dua kondisi terjadi (asumsikan bahwa klien dapat disesuaikan dengan salah satu opsi):

  1. Kembalikan kode http 401 (tidak resmi) jika sesi menjadi tidak valid atau kembalikan kode 412 (prasyarat gagal) ketika token telah kedaluwarsa dan sudah waktunya untuk memanggil renew titik akhir, yang akan mengembalikan kode 200 (ok).
  2. Kembalikan 401 untuk memberi isyarat bahwa sesi tidak valid atau token telah kedaluwarsa. Dalam hal ini klien akan segera memanggil renewtitik akhir, jika mengembalikan 200 maka token di-refresh, tetapi jika renewjuga mengembalikan 401 maka itu berarti bahwa klien keluar dari sistem.

Manakah dari dua alternatif di atas yang akan Anda rekomendasikan? Yang mana yang lebih standar, lebih sederhana untuk dipahami, dan / atau lebih tenang? Atau apakah Anda akan merekomendasikan pendekatan yang berbeda sama sekali? Apakah Anda melihat masalah yang jelas atau risiko keamanan dengan salah satu opsi? Poin tambahan jika jawaban Anda menyertakan referensi eksternal yang mendukung pendapat Anda.

MEMPERBARUI

Guys, tolong fokus pada pertanyaan sebenarnya - mana dari dua alternatif kode http untuk menandakan perpanjangan / sesi invalidasi adalah yang terbaik? Jangan pedulikan fakta bahwa sistem saya menggunakan JWT dan sesi sisi server, itu adalah kekhasan API saya untuk aturan bisnis yang sangat spesifik, dan bukan bagian yang saya cari bantuannya;)

Óscar López
sumber
Bagaimana sesi pengguna menjadi tidak valid sebelum token berakhir, dengan asumsi waktu kedaluwarsa singkat (sekitar 5 menit)?
Jack
Karena aturan bisnis, bagian lain dari sistem mungkin membatalkan sesi.
Óscar López
1
JWT adalah untuk bukti identitas, seperti dalam "permintaan ini terbukti dari pengguna X". Jika aturan bisnis Anda adalah sesuatu seperti "pengguna X tidak lagi diizinkan untuk berinteraksi dengan sumber daya Y", itu adalah sesuatu yang harus diperiksa secara terpisah dari JWT.
Jack
@ Jack persis! itulah poin saya tepatnya, dan alasan mengapa saya harus menggunakan lapisan tambahan yang stateful untuk menyimpan informasi sesi. JWT biasa, sebaik mungkin, tidak cocok untuk pekerjaan ini.
Óscar López
1
Kalau begitu, Anda mungkin tertarik dengan jawaban saya :)
Jack

Jawaban:

22

Ini terdengar seperti kasus otentikasi versus otorisasi .

JWT adalah klaim yang ditandatangani secara kriptografis tentang pencetus permintaan. JWT mungkin berisi klaim seperti "Permintaan ini untuk pengguna X" dan "Pengguna X memiliki peran administrator". Mendapatkan dan memberikan bukti ini melalui kata sandi, tanda tangan, dan TLS adalah domain otentikasi - membuktikan bahwa Anda adalah siapa Anda sebenarnya.

Apa yang mereka klaim berarti ke server Anda - apa yang pengguna tertentu dan peran diizinkan untuk melakukan - adalah masalah otorisasi . Perbedaan antara keduanya dapat dijelaskan dengan dua skenario. Misalkan Bob ingin memasuki bagian penyimpanan terbatas di gudang perusahaannya, tetapi pertama-tama ia harus berurusan dengan seorang penjaga bernama Jim.

Skenario A - Otentikasi

  • Bob: "Halo Jim, saya ingin memasukkan penyimpanan terbatas."
  • Jim: "Apakah Anda punya lencanamu?"
  • Bob: "Tidak, lupakan saja."
  • Jim: "Maaf sobat, tidak ada entri tanpa lencana."

Skenario B - Otorisasi

  • Bob: "Halo Jim, saya ingin memasukkan penyimpanan terbatas. Ini lencana saya."
  • Jim: "Hei Bob, Anda perlu izin level 2 untuk masuk ke sini. Maaf."

Waktu kedaluwarsa JWT adalah perangkat otentikasi yang digunakan untuk mencegah orang lain mencuri mereka. Jika semua JWT Anda memiliki waktu kedaluwarsa lima menit, itu bukan masalah besar jika dicuri karena mereka dengan cepat menjadi tidak berguna. Namun, "kedaluwarsa sesi" aturan yang Anda diskusikan terdengar seperti masalah otorisasi. Beberapa perubahan status berarti bahwa pengguna X tidak lagi diizinkan untuk melakukan sesuatu yang sebelumnya dapat mereka lakukan. Misalnya, pengguna Bob mungkin telah dipecat - tidak masalah bahwa lencananya mengatakan dia adalah Bob lagi, karena hanya menjadi Bob tidak lagi memberinya wewenang dengan perusahaan.

Dua kasus ini memiliki kode respons HTTP berbeda: 401 Unauthorizeddan 403 Forbidden. Kode 401 yang sayangnya bernama untuk masalah otentikasi seperti kredensial hilang, kedaluwarsa, atau dicabut. 403 untuk otorisasi, di mana server tahu persis siapa Anda, tetapi Anda tidak diizinkan melakukan hal yang ingin Anda lakukan. Dalam hal akun pengguna dihapus, mencoba melakukan sesuatu dengan JWT di titik akhir akan menghasilkan respons Terlarang 403. Namun, jika JWT kedaluwarsa, hasil yang benar adalah 401 Tidak Resmi.

Pola JWT yang umum adalah memiliki token "berumur panjang" dan "berumur pendek". Token berumur panjang disimpan pada klien seperti token berumur pendek, tetapi tokennya terbatas dan hanya digunakan dengan sistem otorisasi Anda untuk mendapatkan token berumur pendek. Token berumur panjang, seperti namanya, memiliki periode kedaluwarsa yang sangat panjang - Anda dapat menggunakannya untuk meminta token baru selama berhari-hari atau berminggu-minggu. Token berumur pendek adalah token yang Anda gambarkan, digunakan dengan waktu kedaluwarsa yang sangat singkat untuk berinteraksi dengan sistem Anda. Token berumur panjang berguna untuk mengimplementasikan fungsi Remember Me, jadi Anda tidak perlu memberikan kata sandi setiap lima menit untuk mendapatkan token baru yang berumur pendek.

Masalah "sesi tidak valid" yang Anda gambarkan terdengar mirip dengan mencoba membatalkan JWT yang berumur panjang, karena yang berumur pendek jarang disimpan di sisi server sedangkan yang berumur panjang dilacak jika mereka perlu dicabut. Dalam sistem seperti itu, upaya untuk memperoleh kredensial dengan token berumur panjang yang dicabut akan menghasilkan 401 Tidak Sah, karena pengguna mungkin secara teknis dapat memperoleh kredensial tetapi token yang mereka gunakan tidak cocok untuk tugas tersebut. Kemudian ketika pengguna mencoba memperoleh token baru yang berumur panjang menggunakan nama pengguna dan kata sandi mereka, sistem dapat merespons dengan 403 Forbidden jika mereka dikeluarkan dari sistem.

Mendongkrak
sumber
3
Ini adalah panduan yang saya cari, dan Anda membawa wawasan yang sangat relevan untuk diskusi - bahwa ini adalah kasus otentikasi vs otorisasi, dan masing-masing harus ditangani secara berbeda. Terima kasih!
Óscar López
16

Sesi API Anda adalah hal yang seharusnya tidak ada di dunia yang tenang sama sekali. Operasi yang tenang seharusnya tanpa kewarganegaraan, sesi berisi keadaan dan dengan demikian tidak memiliki tempat di dunia yang tenang.

JWT harus menjadi satu-satunya cara Anda untuk menentukan apakah pengguna masih memenuhi syarat untuk mengakses titik akhir atau tidak. Sesi seharusnya sama sekali tidak memainkan peran di dalamnya. Jika ya, Anda tidak memiliki API yang tenang.

Ketika Anda menghilangkan sesi sama sekali, yang jika Anda bertujuan untuk RESTful API yang harus Anda lakukan, dan hanya menggunakan JWT sebagai faktor autentikasi, pengguna entah berwenang untuk menggunakan titik akhir Anda atau tidak - dalam hal ini 401 Unauthorizedkode respons sesuai - dan harus menghubungi renewtitik akhir dengan grant_type=refresh_tokenatau identifikasi pembaruan apa pun yang Anda gunakan.

Memperbarui:

Dari komentar sepertinya aliran validasi JWT yang Anda gunakan saat ini tidak benar. Validasi seharusnya terlihat seperti ini:

  Client        RESTful API      JWT Issuer
     |              |                |
     |----- 1. ---->|                | 
     |              |------ 2. ----->|-----
     |              |                | 3. |
     |              |<----- 4. ------|<----
-----|<---- 5. -----|                |
| 6. |              |                |
---->|----- 7. ---->|                |
     |              |------ 8. ----->|-----
     |              |                | 9. |
     |              |<----- 10. -----|<----
     |              |                |
     |              |------          |
     |              | 11. |          |
     |<---- 12. ----|<-----          |
     |              |                |
     .              .                .

1. Ask RESTful API for a JWT using login endpoint.
2. Ask Issuer to create a new JWT.
3. Create JWT.
4. Return JWT to the RESTful API.
5. Return JWT to Client.
6. Store JWT to append it to all future API requests.
7. Ask for data from API providing JWT as authorization.
8. Send JWT to Issuer for verification.
9. Issuer verifies JWT.
10. Issuer returns 200 OK, verification successful.
11. Retrieve and format data for Client.
12. Return data to Client.

Server,, RESTful APIharus memeriksa validitas token yang dikirim sebagai Otorisasi. Itu bukan tanggung jawab Client. Sepertinya Anda saat ini tidak melakukan ini. Laksanakan verifikasi JWT dengan cara ini dan Anda tidak perlu sesi sama sekali.

Andy
sumber
Terima kasih atas jawaban anda. Setuju, menggunakan sesi tidak akan menjadi pendekatan 100% tenang, tetapi seperti yang saya sebutkan di atas, saya perlu menolak akses ke beberapa pengguna sebelum token berakhir.
Óscar López
2
@ ÓscarLópez Kemudian cukup batalkan token yang digunakan pengguna. Mereka tidak akan lagi dapat mengakses API menggunakan token yang disediakan (yang sekarang sudah tidak valid) dan Anda tidak perlu sesi.
Andy
1
Token disimpan di klien, bagaimana saya bisa membatalkannya di sana? Saya harus melacak yang mana yang valid ... dan di situlah negara menggunakan kepala jeleknya. Terkadang itu tidak bisa dihindari.
Óscar López
Klien jahat dapat terus mengirim token yang sebelumnya valid selama waktu kedaluwarsa memungkinkannya, tetapi saya perlu mengusirnya dari sistem segera - maka pengaturan waktu pembaruan yang singkat juga bukan pilihan.
Óscar López
4
@Laiv Saya membuat diagram urutan di notepad.
Andy
1

Jadi, saya akui bahwa tidak masuk akal bagi saya untuk khawatir tentang pendekatan mana yang paling TENANG ketika Anda sudah melanggar konvensi REST dengan sesi ini, tapi saya mengerti memuaskan kebutuhan bisnis Anda.

Dari sudut pandang REST, klien diautentikasi, atau tidak. Arsitekturnya tidak terlalu peduli mengapa (itu menyuntikkan keadaan yang tidak perlu), jadi untuk menjawab pertanyaan utama Anda, saya tidak akan memiliki titik akhir yang diperbarui sama sekali. Klien yang masuk hanya akan selalu mengirim JWT mereka dan server selalu memvalidasinya dan menerima dengan mengirim kode Sukses yang sesuai berdasarkan tindakan 200, 201, dll.) Atau menolak dengan 401 atau 403 yang sesuai.

Sekarang, JWT akan dikaitkan dengan semacam akun. Akun itu mungkin dikunci atau dibatasi atau apa pun, dan token itu sendiri mungkin valid tetapi tindakannya masih ditolak di tempat lain. Jika kasusnya adalah bahwa akun pengguna dikunci karena aturan bisnis, maka itu masih 401 atau 403 tergantung pada seberapa banyak info yang ingin Anda berikan kepada klien (bisnis yang berbeda memiliki pendapat berbeda tentang itu).

Akhirnya, jika Anda menyatakan bahwa akun tersebut mungkin tidak dikunci dan valid tetapi JWT hanya perlu dicabut, maka saya akan MASIH tetap dengan 401 atau 403 dan mempertahankan sesuatu seperti Daftar Pencabutan Sertifikat JWT yang tidak valid yang dapat Anda masukkan ke dalamnya. , asalkan membersihkan sendiri ketika JWT akan kedaluwarsa (kebanyakan database memiliki cara untuk melakukan itu atau Anda dapat memiliki acara dalam kode aplikasi).

Paul
sumber
jwt seharusnya tanpa kewarganegaraan. saat Anda mempertanyakan kontennya dan memvalidasinya terhadap db, tidak lagi tanpa kewarganegaraan sehingga menjadi berlebihan karena ada solusi yang lebih baik untuk sesi statefull
Stavm