36 คะแนน โดย GN⁺ 2024-05-28 | 8 ความคิดเห็น | แชร์ทาง WhatsApp
  • JWT ย่อมาจาก JSON Web Tokens และเป็นมาตรฐานสำหรับโทเค็นยืนยันตัวตน
  • JWT ประกอบด้วย header, payload, signature หรือ message authentication code
  • ผู้ที่มีคีย์สำหรับตรวจสอบสามารถยืนยันความถูกต้องแท้จริงของ payload ได้

รูปแบบการใช้งาน JWT ทั่วไป

  • JWT มีข้อมูลอย่างเช่น issuer, audience, subject และเวลาหมดอายุ
  • ผู้รับจะตรวจสอบความถูกต้องของโทเค็น จากนั้นตรวจว่าหมดอายุหรือยัง และถือว่า subject คือผู้ใช้ที่ผ่านการยืนยันตัวตนแล้ว

ข้อดีของ JWT

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

ปัญหาเรื่องการล็อกเอาต์และการทำให้เซสชันเป็นโมฆะ

  • โทเค็นยืนยันตัวตนควรมีอายุสั้น เช่น สูงสุด 5 นาที
  • ไคลเอนต์จะได้รับ refresh token ด้วย เพื่อใช้ขอโทเค็นยืนยันตัวตนใหม่
  • refresh token ทำหน้าที่เป็นโทเค็นเซสชันตัวจริง

กรณีที่ไม่จำเป็นต้องใช้ JWT

  • หากต้องการทำระบบล็อกเอาต์ ต้องเก็บ allowlist ของ JWT ที่ยังใช้ได้ หรือ denylist ของ JWT ที่ถูกเพิกถอน
  • หากต้องการบล็อกผู้ใช้ ต้องตรวจสอบแฟลก "ผู้ใช้ยังใช้งานอยู่" ในฐานข้อมูล
  • ต้องมีความสัมพันธ์เพิ่มเติมระหว่างออบเจ็กต์ผู้ใช้กับออบเจ็กต์อื่น
  • มีการทำงานที่เกี่ยวข้องกับฐานข้อมูล

บทสรุป

  • หากเข้าเงื่อนไขข้อใดข้อหนึ่งข้างต้น ก็ไม่จำเป็นต้องใช้ JWT
  • การใช้ session token แบบ opaque ทั่วไปและเก็บไว้ในฐานข้อมูลจะดีกว่า
  • สามารถหลีกเลี่ยงข้อเสียของ JWT และลดความซับซ้อนได้

ความเห็นของ GN⁺

  • JWT เหมาะกับบริการขนาดใหญ่ แต่สำหรับบริการขนาดเล็กส่วนใหญ่ อาจเพิ่มความซับซ้อนเกินความจำเป็น
  • กลไกจัดการเซสชันแบบทั่วไปเพียงพอสำหรับเว็บแอปพลิเคชันส่วนใหญ่
  • การใช้ JWT อาจทำให้การทำฟีเจอร์อย่างการล็อกเอาต์และการทำให้เซสชันเป็นโมฆะทำได้ยาก
  • หากต้องการใช้ประโยชน์จากข้อดีของ JWT ควรพิจารณาขนาดและข้อกำหนดของบริการอย่างรอบคอบ
  • อีกทางเลือกหนึ่งคือพิจารณาเฟรมเวิร์กด้านการยืนยันตัวตนอย่าง OAuth2

8 ความคิดเห็น

 
dhlee0305 2024-05-30

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

 
koxel 2024-05-28

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

 
namarie32ilu 2024-05-28

จากประสบการณ์ส่วนตัว ตอนทำ MVP ผมมองว่า JWT ก็มีข้อดีอยู่ครับ

ยกตัวอย่างเช่น ถ้าเป็นบริการที่ทำและดูแลคนเดียว ก็เหมือนเป็นการลดต้นทุนด้านการวางแผนจากคำขอที่เข้ามาแบบกะทันหัน เพราะความสัมพันธ์ของข้อมูลที่วางไว้ตอนแรก พอผ่านไปเดือนสองเดือนก็มักเปลี่ยนไปโดยสิ้นเชิง ในช่วงที่แผนงานยังไม่ชัดเจน ถ้าเป็นเรื่องที่เกี่ยวกับ auth ผมจำได้ว่าการจัดโครงสร้าง JWT payload ให้มีลักษณะเป็น optional field แล้วทำฟีเจอร์ไว้ก่อน ทำให้แม้ฝั่งวางแผนจะยังไม่ต้องทำงานแยกโดเมนกับแยกบริการ ก็ยังสามารถพัฒนาในรูปแบบที่แยกแค่โดเมนออกจากบริการแบบ monolithic ได้ง่าย ๆ แล้วนำไปทดสอบตลาดก่อนได้ (แล้วค่อยไปตามขั้นตอนแยกบริการภายหลัง หรือไม่ก็ยกเลิกไปเลย)

แต่ทั้งนี้ก็คงขึ้นอยู่กับโดเมนของบริการที่ต้องการสร้างด้วยครับ โปรเจ็กต์นั้นเป็นโปรเจ็กต์ที่มีการผูกกับ third party สูงมากแม้จะเป็นบริการแบบเรียลไทม์ก็ตาม... เลยจำได้ว่าตอนนั้นเลือกแนวทางนี้เพราะคิดว่าถ้ารีบพัฒนาไปมาก ๆ แล้วมี document/row ในฐานข้อมูลสะสมมหาศาล ต้นทุนในการจัดการน่าจะสูงขึ้น

แน่นอนว่าถ้าจะโฟกัสที่การทำให้เสร็จเร็ว ผมมองว่าวิธีแบบ session น่าจะดีกว่า (เพราะช่วงแรก ๆ coupling ระหว่างหลายบริการยังไม่แน่นมาก จะรื้อแล้วทำใหม่ก็สะดวก) แถมเวลาเพื่อนร่วมทีมคนอื่นเข้ามา ต้นทุนในการส่งต่องานก็ต่ำกว่าด้วย

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

 
superwoou 2024-05-28

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

 
namarie32ilu 2024-05-30

โดยภาพรวมก็ใกล้เคียงกับที่คุณพูดไว้ครับ เพียงแต่ในกรณีนี้ไม่ได้ถึงขั้นต้องเปลี่ยนข้อมูลบ่อยเพราะโมเดลของผู้ใช้เองเปลี่ยนไป แต่จะใกล้กับกรณีที่มีการเพิ่มข้อมูลแบบ optional มากกว่า เมื่อมีการเพิ่มฟีเจอร์ใหม่หรือมีบริการใหม่ที่ต้องใช้ third-party tool ซึ่งต้องการข้อมูลเพิ่มเติมของผู้ใช้ (ถ้าจะลงรายละเอียดอีกนิด ก็คืออยู่ในสถานการณ์ที่ยังคลุมเครือว่าในอนาคตจะแยกหน่วยการจัดการ auth ออกไปด้วยอะไรอย่าง API gateway หรือไม่ หรือจะมีเซิร์ฟเวอร์ตัวหนึ่งที่ทำหน้าที่ใกล้เคียงกันหรือเปล่า...)

ถ้ายกตัวอย่างให้เป็นรูปธรรมขึ้นอีกหน่อย ตอนนั้นเป็นสถานการณ์ที่มีบริการ A เป็นตัวหลักอยู่ครับ เนื่องจากยังเป็นช่วง MVP จึงมีเพียงข้อมูลการชำระเงินหรือข้อมูลว่าเป็นผู้ใช้ที่ยืนยันตัวตนแล้วหรือไม่อยู่ในตารางผู้ใช้ แต่มีคำขอเข้ามาให้เพิ่มบริการ B และ C ซึ่งผู้ใช้แต่ละคนต้องมีข้อมูลการยืนยันตัวตนที่ต่างกันจึงจะใช้งานได้ ในบรรดานั้น B เองก็ยังไม่แน่ชัดว่าจะถูกรวมเข้าไปในบริการ A หรือไม่ ส่วน C ก็อาจหายไปได้ จึงอยากทดลองแบบเบา ๆ ก่อน (และฟีเจอร์จัดการแพลนนั้น ต่อให้ไม่พูดก็ควรต้องเพิ่มไว้เพื่อกันปัญหาอยู่แล้ว) นอกจากนี้ยังต้องการเริ่มต้นในรูปแบบที่ให้ B และ C ใช้งานร่วมกันได้บนหน้าเว็บบริการเดิมที่ให้บริการ A อยู่ด้วย ด้วยลักษณะของบริการที่เปิดใช้งานอยู่ ขณะที่ยังไม่ได้สร้างตารางจัดการแพลน (หรือตารางเกี่ยวกับการยืนยันตัวตนแบบทั่วไป) แล้ววาดความสัมพันธ์ของโดเมนแยกตามแต่ละบริการเพื่อทำ mapping นั้น การ query หลายตาราง (หรือหลายคอลเลกชัน) จึงเป็นสิ่งที่หลีกเลี่ยงไม่ได้ ในสถานการณ์ที่มีคนมาช่วยจัดระเบียบโปรเจกต์ ก็คงอยากประชุมกันสักสองสามครั้งเพื่อสกัดให้ชัดว่าปัญหาที่ต้องการแก้จริง ๆ คืออะไร และฟีเจอร์ที่ต้องการจริง ๆ คืออะไร แต่ตอนนั้นไม่ได้อยู่ในสภาพแวดล้อมที่รับประกันได้ว่าจะทำแบบนั้นได้ อีกทั้งก็ไม่ชัดเจนด้วยว่าจะสามารถทยอยชำระหนี้ทางเทคนิคพวกนี้ได้เมื่อไร ดังนั้นเรื่องแบบนี้จึงเป็นสิ่งที่พอคาดได้ตั้งแต่ก่อนเปิดตัวบริการ A แล้ว... พอคิดตั้งแต่ตอนวางโครงสร้างแรกว่าจะออกแบบฝั่ง auth ให้ประหยัดต้นทุนการ query และต้นทุนการดูแลในอนาคตให้มากที่สุด ก็เลยเลือกใช้ JWT ครับ นอกจากนี้ก็เหมือนจะมีเรื่องยิบย่อยลักษณะคล้าย ๆ กันอีกเยอะมากด้วย

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

 
a1eng0 2024-05-28
  • กรณีที่สามารถนำ JWT ไปใช้ได้มีไม่มาก และโดยส่วนใหญ่แนวทางแบบเซสชันดั้งเดิมจะเหมาะสมกว่า
  • นักพัฒนาจำนวนมากกว่าที่คิดเข้าใจแก่นแท้ของ JWT ผิดไป และมักสื่อสารกันโดยมองข้ามข้อเสียหลายอย่างด้วยแนวคิดทำนองว่า "ใช้สิ่งนี้แล้วจะใช้ DB น้อยลง, ประสิทธิภาพจะเร็วขึ้น"
  • พอการสื่อสารเอนเอียงไปในทิศทางนั้น ก็ต้องเริ่มอธิบายตั้งแต่แก่นแท้ของการยืนยันตัวตนแบบกุญแจสาธารณะและลายเซ็นดิจิทัล ซึ่งทำให้ปวดหัวมาก
  • เดิมที JWT ไม่ได้เป็นสิ่งที่อยู่ในข่ายต้องพิจารณา แต่ก็มักมีประสบการณ์ที่มันดึงการประชุมให้ไหลไปในทิศทางแปลก ๆ ราวกับหลุมดำอยู่บ่อยครั้ง
 
newro 2024-05-30

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

 
GN⁺ 2024-05-28
ความเห็นจาก Hacker News

สรุปความคิดเห็นจาก Hacker News

  • แนะนำให้ใช้กลไกเซสชันแบบดั้งเดิม: ควรใช้กลไกเซสชันทั่วไปที่เว็บเฟรมเวิร์กมีให้ JWT ไม่ได้จำเป็นในทุกกรณี
  • การใช้ JWT ในสถาปัตยกรรมไมโครเซอร์วิส: ในสภาพแวดล้อมแบบไมโครเซอร์วิส JWT มีประโยชน์ แต่สำหรับเว็บแอปแบบโมโนลิธิกเดี่ยว ความจำเป็นมีน้อยกว่า
  • ปัญหาด้านความปลอดภัยของ JWT: JWT อาจมีช่องโหว่ด้านความปลอดภัยได้ แต่ส่วนใหญ่เกิดจากการใช้ไลบรารีที่ไม่ถูกต้องหรือการตั้งค่าที่ผิด หากใช้ไลบรารีที่เชื่อถือได้ก็ไม่มีปัญหา
  • ประสบการณ์การใช้ JWT: มีประสบการณ์ที่ใช้ JWT เพื่อแก้ปัญหา และไม่รู้สึกเสียใจที่เลือกใช้
  • การใช้ AWS Cognito: หากใช้ AWS Cognito จัดการการยืนยันตัวตน ก็สามารถทำ MFA, social login, การยืนยันอีเมล ฯลฯ ได้ง่าย ข้อเสียของ JWT แก้ได้ด้วยอายุการใช้งานที่สั้นและการรีเฟรชบ่อยครั้ง
  • JWT กับบริการภายนอก: มักใช้ JWT กับบริการภายนอกบ่อยครั้ง การใช้ JWT ทำให้นักพัฒนาจำเป็นต้องเข้าใจเพียงแนวคิดเดียว
  • การใช้ JWT ในสภาพแวดล้อมขนาดเล็ก: แม้ในสภาพแวดล้อมขนาดเล็ก JWT ก็อาจมีประโยชน์ได้ สามารถจำกัดการเข้าถึงข้อมูลที่อ่อนไหวและช่วยลดต้นทุนได้
  • การเปรียบเทียบ JWT กับเซสชันโทเค็น: การติดตั้งใช้งาน JWT จริงจำนวนมากมักแลก JWT เป็นเซสชันโทเค็น JWT มีประโยชน์เมื่อ IDP ใช้ยืนยันตัวตนของผู้ใช้
  • ข้อดีของ JWT: สามารถทำให้ระบบยืนยันตัวตนเป็นมาตรฐานผ่าน OAuth 2 และ OIDC และจัดการการยืนยันตัวตนของฝั่งฟรอนต์เอนด์กับ API ในรูปแบบเดียวกันได้
  • ความสะดวกของการใช้ JWT: ในสภาพแวดล้อมอย่าง Azure การใช้ JWT ทำให้เข้าถึงหลาย API ได้โดยไม่ต้องกังวลเรื่องสถานะของเซสชัน
  • การใช้ JWT ในการยืนยันตัวตนระหว่างเครื่อง: สำหรับการยืนยันตัวตนระหว่างเครื่อง JWT เหมาะสมที่สุด เช่น ใช้ JWT ในการสื่อสารระหว่าง Raspberry Pi เพื่อจัดการการยืนยันตัวตนและการกำหนดสิทธิ์