การจัดการการต่ออายุโทเค็น / การหมดอายุเซสชันใน RESTful API


17

ฉันกำลังสร้าง RESTful API ที่ใช้โทเค็น JWT สำหรับการรับรองความถูกต้องของผู้ใช้ (ที่ออกโดยloginปลายทางและส่งในส่วนหัวทั้งหมดหลังจากนั้น) และโทเค็นต้องได้รับการรีเฟรชหลังจากระยะเวลาคงที่ (เรียกrenewจุดสิ้นสุด )

เป็นไปได้ว่าเซสชัน API ของผู้ใช้จะไม่ถูกต้องก่อนที่โทเค็นจะหมดอายุดังนั้นจุดสิ้นสุดทั้งหมดของฉันเริ่มต้นด้วยการตรวจสอบว่า: 1) โทเค็นยังคงถูกต้องและ 2) เซสชันของผู้ใช้ยังคงถูกต้อง ไม่มีวิธีในการทำให้โทเค็นเป็นโมฆะโดยตรงเนื่องจากไคลเอนต์เก็บไว้ในเครื่อง

ดังนั้นจุดสิ้นสุดของฉันทั้งหมดต้องส่งสัญญาณให้ลูกค้าทราบถึงสองเงื่อนไขที่เป็นไปได้: 1) ถึงเวลาต่ออายุโทเค็นหรือ 2) เซสชันนั้นไม่ถูกต้องและพวกเขาไม่ได้รับอนุญาตให้เข้าถึงระบบอีกต่อไป ฉันสามารถนึกถึงทางเลือกสองทางสำหรับจุดสิ้นสุดของฉันในการส่งสัญญาณลูกค้าเมื่อเกิดหนึ่งในสองเงื่อนไข (สมมติว่าลูกค้าสามารถปรับให้เข้ากับตัวเลือกใดตัวเลือกหนึ่ง):

  1. ส่งคืนรหัส http 401 (ไม่ได้รับอนุญาต) หากเซสชันไม่ถูกต้องหรือส่งคืนรหัส 412 (เงื่อนไขเบื้องต้นล้มเหลว) เมื่อโทเค็นหมดอายุและถึงเวลาเรียกrenewจุดสิ้นสุดซึ่งจะส่งคืนรหัส 200 (ok)
  2. ส่งคืน 401 สำหรับการส่งสัญญาณว่าเซสชันไม่ถูกต้องหรือโทเค็นหมดอายุแล้ว ในกรณีนี้ลูกค้าจะโทรหาrenewปลายทางทันทีถ้ามันคืน 200 โทเค็นจะถูกรีเฟรช แต่ถ้าrenewกลับ 401 ก็หมายความว่าไคลเอนต์ออกจากระบบ

คุณจะแนะนำทางเลือกใดจากสองข้อด้านบน อันไหนจะเป็นมาตรฐานมากขึ้นเข้าใจง่ายและ / หรือสงบมากขึ้น? หรือคุณจะแนะนำวิธีการอื่นโดยสิ้นเชิง? คุณเห็นปัญหาที่ชัดเจนหรือความเสี่ยงด้านความปลอดภัยที่มีตัวเลือกอย่างใดอย่างหนึ่ง? คะแนนพิเศษหากคำตอบของคุณมีการอ้างอิงภายนอกที่สนับสนุนความคิดเห็นของคุณ

UPDATE

พวกโปรดมุ่งเน้นไปที่คำถามจริง - ตัวเลือกรหัส http สองตัวใดในการส่งสัญญาณการตรวจสอบความถูกต้องของการต่ออายุ / เซสชันนั้นดีที่สุด? ไม่ต้องสนใจความจริงที่ว่าระบบของฉันใช้ JWT และเซสชันฝั่งเซิร์ฟเวอร์นั่นเป็นลักษณะเฉพาะของ API ของฉันสำหรับกฎเกณฑ์ทางธุรกิจที่เฉพาะเจาะจงไม่ใช่ส่วนที่ฉันต้องการความช่วยเหลือ;)


เซสชันของผู้ใช้จะไม่ถูกต้องอย่างไรก่อนที่โทเค็นจะหมดอายุสมมติว่าเวลาหมดอายุสั้น ๆ (ประมาณ 5 นาที)
แจ็ค

เนื่องจากกฎทางธุรกิจส่วนต่าง ๆ ของระบบอาจทำให้เซสชันไม่ถูกต้อง
ÓscarLópez

1
JWT มีไว้เพื่อพิสูจน์ตัวตนเช่นเดียวกับใน "คำขอนี้พิสูจน์แล้วว่ามาจากผู้ใช้ X" หากกฎธุรกิจของคุณเป็นสิ่งที่ "ผู้ใช้ X ไม่ได้รับอนุญาตให้มีปฏิสัมพันธ์กับทรัพยากร Y" อีกต่อไปนั่นคือสิ่งที่ควรตรวจสอบแยกต่างหากจาก JWT
แจ็ค

@ แจ็คแน่นอน! นั่นคือประเด็นของฉันอย่างแม่นยำและเหตุผลที่ฉันต้องใช้เลเยอร์เพิ่มเติมที่เป็นประโยชน์สำหรับการบันทึกข้อมูลเซสชัน เจดับบลิวทีธรรมดาที่ดีอย่างที่มันเป็นก็ไม่ได้ถูกตัดสำหรับงาน
ÓscarLópez

1
คุณอาจสนใจคำตอบของฉันแล้ว :)
แจ็ค

คำตอบ:


22

เสียงนี้เช่นกรณีที่มีการรับรองความถูกต้องเมื่อเทียบกับการอนุมัติ

JWT เป็นข้อเรียกร้องที่เซ็นชื่อแบบเข้ารหัสลับเกี่ยวกับผู้ส่งคำขอ JWT อาจมีการอ้างสิทธิ์เช่น "คำขอนี้มีไว้สำหรับผู้ใช้ X" และ "ผู้ใช้ X มีบทบาทผู้ดูแลระบบ" การรับและการให้การพิสูจน์นี้ผ่านรหัสผ่านลายเซ็นและ TLS เป็นโดเมนของการตรวจสอบ - พิสูจน์ว่าคุณคือคนที่คุณพูดว่าคุณเป็น

สิ่งที่เรียกร้องเหล่านั้นหมายความว่ายังเซิร์ฟเวอร์ของคุณ - สิ่งที่ผู้ใช้ที่เฉพาะเจาะจงและบทบาทได้รับอนุญาตให้ทำ - คือปัญหาของการอนุมัติ ความแตกต่างระหว่างทั้งสองสามารถอธิบายได้ด้วยสองสถานการณ์ สมมติว่าบ็อบต้องการเข้าสู่ส่วนจัดเก็บที่ จำกัด ของคลังสินค้าของ บริษัท แต่ก่อนอื่นเขาต้องจัดการกับผู้พิทักษ์ที่ชื่อจิม

สถานการณ์จำลอง A - การพิสูจน์ตัวตน

  • Bob: "สวัสดี Jim ฉันต้องการป้อนที่เก็บข้อมูลแบบ จำกัด "
  • จิม: "คุณได้ป้ายแล้วหรือยัง?"
  • Bob: "ไม่ลืมมันไปเถอะ"
  • จิม: "ขอโทษเพื่อนไม่มีรายการโดยไม่มีป้าย"

สถานการณ์ B - การอนุญาต

  • Bob: "สวัสดี Jim ฉันต้องการป้อนที่เก็บข้อมูลแบบ จำกัด นี่คือตราของฉัน"
  • จิม: "เฮ้บ๊อบคุณต้องผ่านด่านระดับ 2 เพื่อเข้ามาที่นี่ขออภัย"

เวลาหมดอายุ JWT เป็นอุปกรณ์ตรวจสอบความถูกต้องที่ใช้เพื่อป้องกันผู้อื่นจากการขโมย หาก JWT ของคุณทุกคนมีเวลาหมดอายุห้านาทีมันก็ไม่ใช่เรื่องใหญ่โตหากพวกเขาถูกขโมยเพราะพวกเขาจะไร้ประโยชน์อย่างรวดเร็ว อย่างไรก็ตามกฎ "การหมดอายุเซสชัน" ที่คุณพูดถึงฟังดูเหมือนปัญหาการให้สิทธิ์ การเปลี่ยนแปลงบางอย่างในสถานะหมายความว่าผู้ใช้ X ไม่ได้รับอนุญาตให้ทำสิ่งที่พวกเขาเคยทำ ตัวอย่างเช่นผู้ใช้ Bob อาจถูกไล่ออก - มันไม่สำคัญว่าตราของเขาจะบอกว่าเขาคือ Bob อีกต่อไปเพราะการที่ Bob ไม่ได้ให้สิทธิ์ใด ๆ กับ บริษัท อีกต่อไป

ทั้งสองกรณีมีรหัสการตอบสนอง HTTP ที่แตกต่าง: และ401 Unauthorized 403 Forbiddenรหัส 401 ที่น่าเสียดายคือสำหรับปัญหาการตรวจสอบสิทธิ์เช่นข้อมูลรับรองที่ขาดหายไปหมดอายุหรือถูกเพิกถอน 403 สำหรับการอนุญาตที่เซิร์ฟเวอร์รู้ว่าคุณคือใคร แต่คุณไม่ได้รับอนุญาตให้ทำสิ่งที่คุณพยายามทำ ในกรณีที่บัญชีของผู้ใช้ถูกลบการพยายามทำบางสิ่งกับ JWT ที่ปลายทางจะส่งผลให้มีการตอบสนองที่ต้องห้าม 403 อย่างไรก็ตามหาก JWT หมดอายุแล้วผลลัพธ์ที่ถูกต้องจะเป็น 401 Unauthorized

รูปแบบ JWT ทั่วไปคือมีโทเค็นแบบ "มีอายุยืนยาว" และ "อายุสั้น" ราชสกุลอยู่นานจะถูกเก็บไว้กับลูกค้าเช่นราชสกุลอายุสั้น แต่พวกเขากำลัง จำกัด อยู่ในขอบเขตและเพียงใช้กับระบบการอนุมัติของคุณที่จะได้รับราชสกุลสั้น โทเค็นที่มีอายุยืนยาวอย่างที่ชื่อบ่งบอกว่ามีช่วงเวลาหมดอายุที่ยาวมาก - คุณสามารถใช้โทเค็นเหล่านี้เพื่อร้องขอโทเค็นใหม่เป็นวันหรือสัปดาห์ที่สิ้นสุด โทเค็นอายุสั้นเป็นโทเค็นที่คุณอธิบายใช้กับเวลาหมดอายุที่สั้นมากในการโต้ตอบกับระบบของคุณ โทเค็นที่มีอายุการใช้งานยาวนานมีประโยชน์ในการใช้ฟังก์ชั่น Remember Me ดังนั้นคุณไม่จำเป็นต้องใส่รหัสผ่านของคุณทุก ๆ ห้านาทีเพื่อรับโทเค็นอายุสั้นใหม่

ปัญหา "การทำให้เซสชันใช้ไม่ได้" คุณกำลังอธิบายว่าเสียงคล้ายกับการพยายามทำให้ JWT ใช้งานไม่ได้เนื่องจากอายุสั้น ๆ นั้นไม่ค่อยได้รับการจัดเก็บไว้ฝั่งเซิร์ฟเวอร์ในขณะที่คนที่ติดตามมานานจะถูกติดตามในกรณีที่จำเป็นต้องเพิกถอน ในระบบดังกล่าวการพยายามรับข้อมูลประจำตัวด้วยโทเค็นที่ถูกเพิกถอนมาเป็นเวลานานจะส่งผลให้ 401 ไม่ได้รับอนุญาตเนื่องจากผู้ใช้อาจใช้เทคนิคในการรับข้อมูลรับรองได้ แต่โทเค็นที่ใช้ไม่เหมาะสมสำหรับงาน จากนั้นเมื่อผู้ใช้พยายามรับโทเค็นที่มีอายุการใช้งานยาวนานโดยใช้ชื่อผู้ใช้และรหัสผ่านระบบสามารถตอบกลับด้วย 403 สิ่งต้องห้ามหากพวกเขาถูกไล่ออกจากระบบ


3
นี่คือคำแนะนำที่ฉันกำลังมองหาและคุณได้นำข้อมูลเชิงลึกที่เกี่ยวข้องมาสู่การอภิปรายว่านี่เป็นกรณีของการรับรองความถูกต้องกับการอนุญาตและแต่ละข้อควรได้รับการจัดการแตกต่างกัน ขอบคุณ!
ÓscarLópez

16

เซสชัน API ของคุณเป็นสิ่งที่ไม่ควรมีในโลกแห่งความสงบเลย การดำเนินการ RESTful ควรจะไร้สัญชาติเซสชันมีสถานะและไม่มีสถานที่ใดในโลกที่สงบเงียบ

JWT ควรเป็นวิธีเดียวของคุณในการพิจารณาว่าผู้ใช้ยังคงมีสิทธิ์เข้าถึงปลายทางหรือไม่ เซสชั่นควรไม่มีบทบาทอย่างแน่นอน ถ้าใช่คุณไม่มี RESTful API

เมื่อคุณตัดเซสชันทั้งหมดออกไปซึ่งหากคุณต้องการ RESTful API คุณควรทำและใช้ JWT เป็นปัจจัยการตรวจสอบสิทธิ์เท่านั้นผู้ใช้จะได้รับอนุญาตให้ใช้ปลายทางหรือไม่ - ในกรณีที่401 Unauthorizedรหัสตอบกลับเหมาะสม - และควรโทรหาrenewจุดสิ้นสุดด้วยgrant_type=refresh_tokenหรือระบุการต่ออายุใด ๆ

ปรับปรุง:

จากความคิดเห็นดูเหมือนว่ากระแสการตรวจสอบของ JWT ที่คุณกำลังใช้ไม่ถูกต้อง การตรวจสอบควรมีลักษณะเช่นนี้:

  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.

เซิร์ฟเวอร์RESTful APIต้องตรวจสอบความถูกต้องของโทเค็นที่ส่งไปเป็นการอนุญาต Clientที่ไม่ได้เป็นความรับผิดชอบของ ดูเหมือนว่าคุณไม่ได้ทำเช่นนี้ ใช้การตรวจสอบของ JWT ด้วยวิธีนี้และคุณไม่ต้องการเซสชันเลย


ขอบคุณสำหรับคำตอบ. ตกลงการใช้เซสชันจะไม่ใช่วิธี RESTful 100% แต่ตามที่กล่าวไว้ข้างต้นฉันจำเป็นต้องปฏิเสธการเข้าถึงผู้ใช้บางรายก่อนที่โทเค็นจะหมดอายุ
ÓscarLópez

2
@ ÓscarLópezจากนั้นเพียงทำให้โทเค็นที่ผู้ใช้ใช้งานไม่ถูกต้อง พวกเขาจะไม่สามารถเข้าถึง API ได้โดยใช้โทเค็นที่ให้ไว้ (ซึ่งตอนนี้จะถูกทำให้ใช้งานไม่ได้) และคุณไม่ต้องการเซสชัน
แอนดี้

1
โทเค็นถูกเก็บไว้ในไคลเอนต์ฉันจะทำให้โมฆะพวกเขามี ฉันจะต้องติดตามว่าอันไหนที่ถูกต้อง ... และนั่นคือสิ่งที่รัฐพูดถึงสิ่งที่น่าเกลียดที่สุด บางครั้งก็หลีกเลี่ยงไม่ได้
ÓscarLópez

ไคลเอนต์ที่เป็นอันตรายสามารถส่งโทเค็นที่ถูกต้องก่อนหน้านี้ตราบเท่าที่เวลาหมดอายุอนุญาต แต่ฉันต้องเตะเขาออกจากระบบทันที - ดังนั้นการตั้งเวลาต่ออายุสั้น ๆ ก็ไม่ใช่ตัวเลือก
ÓscarLópez

4
@Laiv ฉันทำแผนภาพลำดับใน Notepad
Andy

1

ดังนั้นฉันจะยอมรับว่ามันไม่สมเหตุสมผลสำหรับฉันที่จะกังวลเกี่ยวกับวิธีการที่สงบที่สุดเมื่อคุณได้หยุดการประชุม REST กับเซสชันแล้ว แต่ฉันเข้าใจว่าความต้องการทางธุรกิจของคุณเป็นที่พอใจ

จากมุมมอง REST ไคลเอ็นต์จะได้รับการรับรองความถูกต้องหรือไม่ สถาปัตยกรรมไม่สนใจว่าทำไม (นั่นคือการฉีดสถานะที่ไม่มีความจำเป็น) ดังนั้นเพื่อตอบคำถามหลักของคุณฉันจะไม่ได้รับปลายทางใหม่เลย ลูกค้าที่เข้าสู่ระบบจะส่ง JWT ของตนเสมอและเซิร์ฟเวอร์จะทำการตรวจสอบและยอมรับโดยการส่งรหัสความสำเร็จที่เหมาะสมตามการกระทำ 200, 201 ฯลฯ ) หรือปฏิเสธด้วย 401 หรือ 403 ตามความเหมาะสม

ตอนนี้ JWT กำลังจะเชื่อมโยงกับบัญชีบางประเภท บัญชีนั้นอาจถูกล็อคหรือควบคุมปริมาณหรืออะไรก็ตามโทเค็นนั้นอาจใช้ได้ แต่การกระทำยังคงถูกปฏิเสธที่อื่น หากเป็นกรณีที่บัญชีผู้ใช้ถูกล็อคเนื่องจากกฎเกณฑ์ทางธุรกิจก็ยังคงเป็น 401 หรือ 403 ขึ้นอยู่กับจำนวนข้อมูลที่คุณต้องการให้ลูกค้า (ธุรกิจต่าง ๆ มีความคิดเห็นที่ต่างกัน)

ในที่สุดหากคุณยืนยันว่าบัญชีอาจถูกปลดล็อคและถูกต้อง แต่ JWT เพียงแค่ต้องการที่จะถูกเพิกถอนแล้วฉันจะยังคงติดกับ 401 หรือ 403 และรักษาบางอย่างเช่นรายการเพิกถอนใบรับรองของ JWT ที่ไม่ถูกต้องที่คุณสามารถใส่ไว้ใน ตราบใดที่มันทำความสะอาดตัวเองเมื่อ JWT จะหมดอายุ (ฐานข้อมูลส่วนใหญ่มีวิธีการทำเช่นนั้นหรือคุณสามารถมีเหตุการณ์ในรหัสแอป)


jwt มีจุดมุ่งหมายเพื่อไร้สัญชาติ ช่วงเวลาที่คุณตั้งคำถามกับเนื้อหาและตรวจสอบความถูกต้องกับฐานข้อมูลจะไม่มีสถานะอีกต่อไปจึงกลายเป็นความซ้ำซ้อนเนื่องจากมีวิธีแก้ปัญหาที่ดีกว่าสำหรับเซสชัน statefull
Stavm
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.