การรักษาความปลอดภัย REST API โทเค็นที่เก็บไว้กับ JWT vs OAuth


104

ฉันยังคงพยายามค้นหาโซลูชันความปลอดภัยที่ดีที่สุดสำหรับปกป้อง REST API เนื่องจากจำนวนแอปพลิเคชันมือถือและ API เพิ่มขึ้นทุกวัน

ฉันลองใช้วิธีการพิสูจน์ตัวตนแบบต่างๆ แต่ยังมีความเข้าใจผิดอยู่บ้างดังนั้นฉันต้องการคำแนะนำจากคนที่มีประสบการณ์มากกว่า

ให้ฉันบอกว่าฉันเข้าใจทุกสิ่งนี้ได้อย่างไร หากฉันเข้าใจบางสิ่งผิดพลาดโปรดแจ้งให้เราทราบ

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

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

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

  3. OAuth 2. ฉันไม่เข้าใจว่าทำไมควรใช้วิธีการนี้เมื่อมีการสื่อสารโดยตรงระหว่างเซิร์ฟเวอร์กับลูกค้า เท่าที่ฉันเข้าใจเซิร์ฟเวอร์ OAuth ใช้ในการออกโทเค็นที่มีขอบเขต จำกัด เพื่ออนุญาตให้แอปพลิเคชันอื่นเข้าถึงข้อมูลผู้ใช้โดยไม่ต้องเก็บรหัสผ่านและการเข้าสู่ระบบ นี่เป็นโซลูชันที่ยอดเยี่ยมสำหรับเครือข่ายสังคมเมื่อผู้ใช้ต้องการลงทะเบียนในบางหน้าเซิร์ฟเวอร์สามารถขอสิทธิ์ในการรับข้อมูลผู้ใช้เช่นจาก twitter หรือ facebook และกรอกข้อมูลลงทะเบียนด้วยข้อมูลผู้ใช้และอื่น ๆ

พิจารณาลูกค้ามือถือสำหรับร้านค้าออนไลน์

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

ดังนั้นประโยชน์ของโทเค็น JWT คืออะไร

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


ขอบคุณฉันสงสัยว่าเมื่อเร็ว ๆ นี้ ฉันไปกับการจัดการเซสชัน (บีกเกอร์) และลบโทเค็นเซสชันหลังจากหนึ่งชั่วโมง Oauth ดูไม่เหมาะสม
JasTonAChair

คำตอบ:


86

พิจารณากรณีแรก ลูกค้าแต่ละรายจะได้รับรหัสสุ่มซึ่งจะคงอยู่ตลอดระยะเวลาของเซสชันซึ่งอาจเป็นเวลาหลายวันหากคุณต้องการ จากนั้นคุณเก็บข้อมูลที่เกี่ยวข้องกับเซสชันนั้นไว้ที่ฝั่งเซิร์ฟเวอร์ อาจอยู่ในไฟล์หรือฐานข้อมูล สมมติว่าคุณส่ง ID ผ่านคุกกี้ แต่คุณสามารถใช้ URL หรือส่วนหัว HTTP ได้

รหัสเซสชัน / คุกกี้

ข้อดี:

  • ง่ายต่อการรหัสทั้งลูกค้าและเซิร์ฟเวอร์
  • ง่ายต่อการทำลายเซสชั่นเมื่อมีคนออกจากระบบ

จุดด้อย:

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

โทเค็นเว็บ JSON (JWT)

ในกรณีที่สองข้อมูลจะถูกเก็บไว้ใน JWT ที่ถูกส่งไปรอบ ๆ แทนที่จะเป็นบนเซิร์ฟเวอร์

ข้อดี:

  • ปัญหาการเก็บข้อมูลฝั่งเซิร์ฟเวอร์หายไป
  • รหัสฝั่งไคลเอ็นต์เป็นเรื่องง่าย

จุดด้อย:

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

    ทุกคนที่ได้รับสำเนาของคีย์การลงนามสามารถสร้าง JWT ได้ คุณอาจไม่รู้ว่าเมื่อเกิดเหตุการณ์นี้ขึ้น

    มี (คืออะไร) ข้อผิดพลาดในบางไลบรารีที่ยอมรับ JWT ใด ๆ ที่ลงนามด้วยอัลกอริทึม "none" เพื่อให้ทุกคนสามารถสร้าง JWTs ที่เซิร์ฟเวอร์จะเชื่อถือได้

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

OAuth

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

ข้อดี:

  • ไม่มีรหัสสำหรับผู้ใช้ในการสมัครหรือรีเซ็ตรหัสผ่าน
  • ไม่มีรหัสสำหรับส่งอีเมลพร้อมลิงก์การตรวจสอบแล้วยืนยันที่อยู่
  • ผู้ใช้ไม่จำเป็นต้องเรียนรู้ / จดบันทึกชื่อผู้ใช้และรหัสผ่านอื่น

จุดด้อย:

  • คุณขึ้นอยู่กับบุคคลที่สามเพื่อให้ผู้ใช้สามารถใช้บริการของคุณได้ หากการบริการของพวกเขาหยุดทำงานหรือพวกเขาหยุดให้บริการคุณจะต้องหาวิธีอื่นที่เหมาะสม เช่น: คุณจะย้ายข้อมูลบัญชีผู้ใช้อย่างไรหากข้อมูลประจำตัวของพวกเขาเปลี่ยนจาก "foo@a.com" เป็น "bar@b.com"
  • โดยปกติคุณจะต้องเขียนรหัสสำหรับผู้ให้บริการแต่ละราย เช่น Google, Facebook, Twitter
  • คุณหรือผู้ใช้ของคุณอาจมีความเป็นส่วนตัว ผู้ให้บริการรู้ว่าผู้ใช้รายใดใช้บริการของคุณ
  • คุณกำลังไว้วางใจผู้ให้บริการ เป็นไปได้สำหรับผู้ให้บริการในการออกโทเค็นที่ถูกต้องสำหรับผู้ใช้รายหนึ่งต่อผู้อื่น นี่อาจเป็นไปเพื่อวัตถุประสงค์ทางกฎหมายหรือไม่

เบ็ดเตล็ด

  • ทั้ง ID เซสชันและ JWT สามารถคัดลอกและใช้โดยผู้ใช้หลายคน คุณสามารถจัดเก็บที่อยู่ IP ของลูกค้าใน JWT และตรวจสอบได้ แต่จะป้องกันไม่ให้ลูกค้าโรมมิ่งจากการพูด Wi-Fi ไปยังมือถือ

เพื่อเพิ่มคำตอบของคุณ oAuth อาจไม่เป็นประโยชน์เมื่อผู้ใช้ต้องการลงทะเบียนโดยใช้บัญชี บริษัท ของพวกเขาซึ่งมักจะไม่เกี่ยวข้องหรือเชื่อมโยงกับเว็บไซต์เครือข่ายสังคมออนไลน์หรือ google
Aftab Naveed

5
ฉันไม่รู้ว่าทำไมนี่คือคำตอบที่ยอมรับได้? มันไม่ได้ตอบคำถามที่แท้จริงเพียงปฏิรูปคำถามในลักษณะอื่น
เอเอ็มดี

1
คุณพูดว่า: "ข้อมูลที่เก็บไว้ใน JWT สามารถอ่านได้โดยไคลเอนต์นี่อาจเป็นปัญหา .. ทำไมไม่ใช้ JWE ถ้ามันเป็นปัญหา?
เงิน

คำตอบนี้ทำให้แอปเปิ้ล & ส้มสับสน คุณไม่ควรเปรียบเทียบสิ่งเหล่านี้กับ OAuth 2.0 (ข้อมูลจำเพาะ "การอนุญาต") สิ่งที่ OP ต้องการทราบคือ: "การไหลของรหัสผ่านเจ้าของทรัพยากร" - ซึ่งเป็นการตรวจสอบสิทธิ์
Onur Yıldırım

5

ถามตัวคุณเองว่าทำไมคุณต้องทำให้โทเค็นดั้งเดิมใช้งานไม่ได้

ผู้ใช้ลงชื่อเข้าใช้โทเค็นจะถูกสร้างขึ้นและปิดแอปไป

ผู้ใช้กดล็อกเอาต์โทเค็นใหม่จะถูกสร้างขึ้นและแทนที่โทเค็นดั้งเดิม อีกครั้งทุกอย่างดี

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

ตัวฉันเองไม่คิดว่ามันน่ากังวลเกี่ยวกับ หากมีใครขัดขวางและถอดรหัสข้อมูล https ที่เข้ารหัสของคุณแสดงว่าคุณมีปัญหาที่ใหญ่กว่ามาก

คุณสามารถให้ความคุ้มครองเพิ่มเติมกับตัวเองได้โดยใส่เวลาหมดอายุลงบนโทเค็นต้นฉบับ ดังนั้นหากถูกขโมยหรือทำอะไรบางอย่างมันจะดีในช่วงเวลาสั้น ๆ

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


2
หากคุณคิดว่าลูกค้าของคุณบางคนเป็นอันตรายคุณจะเห็นว่าเซสชันจะถูกคัดลอกและนำกลับมาใช้ใหม่และคุณต้องตอบโต้สิ่งนี้บนเซิร์ฟเวอร์
Michael Shaw

1
ความคิดที่ไม่ดีสามารถใช้งานได้ในภายหลังโดยแฮ็กเกอร์หรือเพียงแค่กำลังดุร้าย ...
CROSP

2
ลองนึกภาพผู้ใช้ที่ต้องการออกจากระบบจากอุปกรณ์อื่นทั้งหมดโดยใช้ JWT เป็นไปไม่ได้
amd

@amd เป็นไปไม่ได้? จะทำอย่างไรถ้าฉันเพิ่ม nonce = (สุ่ม) และหากผู้ใช้ออกจากระบบให้แทนที่ nonce ดูเหมือนง่ายและมีประสิทธิภาพ
Simon B.

3

คุณสามารถจัดการกับปัญหา JWT ที่คุณกล่าวถึงโดยการเก็บค่าเกลือพร้อมกับผู้ใช้และใช้เกลือเป็นส่วนหนึ่งของโทเค็นสำหรับผู้ใช้ จากนั้นเมื่อคุณต้องการทำให้โทเค็นเป็นโมฆะเพียงเปลี่ยนเกลือ

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


4
แต่มันกลับกลายเป็นสถานะรัฐในกรณีนี้ดังนั้นอะไรคือเหตุผลในการสร้างเกลือหรือใช้วิธีการอื่นคุณสามารถเก็บโทเค็นอย่างง่ายในตารางและลบเมื่อควรถูกทำให้เป็นโมฆะ
CROSP

2
นอกจากนี้คุณยังสามารถทำให้เป็นโมฆะตามเวลา
RibaldEddie

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

2
วิธีที่เหมาะสมที่สุดสำหรับการออกจากระบบจากอุปกรณ์เดียวคือให้แน่ใจว่าคุณใช้รหัสลูกค้านอกเหนือจากเกลือ ฉันขอแนะนำให้คุณดูข้อมูลจำเพาะโทเค็นผู้ถือ Oauth-jwt สำหรับข้อมูลเชิงลึก
RibaldEddie

ขอบคุณสำหรับคำตอบ แต่ฉันไม่เข้าใจว่าทำไมฉันควรใช้ OAuth ในกรณีนี้เลย
CROSP
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.