เบื้องหลังการเปลี่ยน Authentication เว็บไซต์จาก Token-based มาเป็น Session-Based

by | Last updated Apr 30, 2020 | DEVELOPERS | 0 comments

นักพัฒนาก่อนจะลงมือสร้างฟีเจอร์ของระบบ จะต้องมีการเช็คบัญชีของผู้ใช้และสิทธิการเข้าถึง วิธีการมีหลายรูปแบบ บทความนี้จะพูดถึง session-based authentication

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

หลังจากเรียนจบ มีความมั่นใจเพิ่มขึ้น จึงได้มาปรับโครงสร้างระบบให้ลูกค้า และคิดว่าการใช้ session-based Auth ในโปรเจคจะช่วยให้เขียนโปรแกรมสะดวก และน่าจะช่วยปิดช่องโหว่สูงขึ้น

ปัญหาของ Token-based Authentication

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

ปัญหาของ Token-based Auth ที่พบทำให้ต้องเปลี่ยนคือ ต่อไปนี้

  • HTTP Protocol เป็นแบบ Stateless เมื่อมีการร้องขอข้อมูลอะไรก็ตาม เซิร์ฟเวอร์จะไม่รู้ว่าเจ้าของคำร้องนี้เป็นของยูสเซอร์ใด ฉะนั้น เราจึงต้องเพิ่ม Token แนบกับ Headers ไปพร้อมกับคำร้อง
  • Revoke token ไม่ได้ต้องรอให้หมดอายุเท่านั้น หากจะให้ Revoke ได้เราจำเป็นต้องเก็บ Token ในฐานข้อมูลเพื่อเป็น BlckList ซึ่งผลลัพธ์สุดท้ายระบบก็จะเป็น Stateful เหมือนเดิม
  • Token ถูกเก็บไว้ใน Local Storage มีโอกาสถูกแฮกเกอร์ขโมย Token แฮกเกอร์จะใช้วิธีป้อนโค้ด JavaScript เพื่อดึงค่าขึ้นมาแล้วนำ token นี้ไปสร้างธุรกรรมที่สำคัญได้ หรือที่เรียกว่า Cross Site Script (XSS) ถูกจัดอันดับของ OWASP
  • JWT Token ใช้อัลกอริทึมที่สามารถแกะข้อมูลภายในมาดู โดยไม่จำเป็นต้องตรวจสอบกับฐานข้อมูล ดังนั้นจึงไม่สามารถเก็บอะไรที่สำคัญ เช่น บทบาท หรือสิทธิ์เข้าถึงระบบ

Session-Based Authentication

Session คือที่เก็บข้อมูล ส่วนใหญ่จะเก็บที่ฝั่ง Server แล้วเอา Session ID ส่งเป็น Cookie ให้ Browser เเทน

เมื่อเราเข้าเว็บไซต์ Session ID จะถูกแนบมากับ HTTP Headers แล้วฝั่ง Server จะเอา Session ID ไปค้นหาดูว่า Session ID ใน Database มีข้อมูลอะไร หรือเรียกว่า Stateful

ขั้นตอนการเปลี่ยน Token ไปเป็น Session

  1. framework ใช้เป็น React กับ Node.js
  2. ใช้ไลบรารี่ express-session และเก็บดาต้าเซสซั่นลง SQL Server ที่เป็นดาต้าเบสของระบบเดิม (ส่วนใหญ่ที่เขาแนะนำให้เก็บลง Redis) ดูรายชื่อไลบรารี่อื่นๆ ที่ตรงกับฐานข้อมูลที่ต้องการ https://www.npmjs.com/package/express-session#compatible-session-stores
  3. เนื่องจาก framework รันบนโดเมนต่างกัน Cookie จะไม่ถูกแนบไปกับ Headers อัตโนมัติ ดังนั้น เราต้องกำหนด credential = include ใน options ของ fetch
  4. กำหนด httpOnly = ture ของ express-session เพื่อไม่ให้ฝั่งไคลเอนต์เห็นข้อมูล cookie ช่วยลดความเสี่ยง XSS
  5. กำหนด Secure = true ของ express-session บังคับให้ไคลเอนต์กับเซิร์ฟเวอร์ ส่งข้อมูล cookie ผ่านทาง HTTPS
  6. กำหนด sameSite = lax ของ express-session เป็นการตั้งค่าให้ server อนุญาตให้โดเมนอื่น request มายัง server เราได้แค่ HTTP Verb GET เท่านั้น POST PUT DELETE ไม่ได้ เพราะ cookie จะถูกป้องกันไม่ให้ส่งไปพร้อมกับ request ช่วยลดความเสี่ยงจาก cross-site request forgery (CSRF)
  7. กำหนด domain ของ express-session ให้ตรงกับโดนเมนหลักเว็บไซต์ เช่น https://www.github.com ให้กำหนดค่าเป็น github.com คือต้องการให้ cookie ถูกเก็บไว้ที่โดเมนนี้เท่านั้น

เมื่อเราติดตั้งทุกอย่างเสร็จแล้ว ให้ตรวจสอบความถูกต้องใน browser แล้วดูที่แถบ cookie storage ใน inspect แสดงตัวอย่าง ดังรูป

ภาพจาก github.com

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

ดังนั้น เราจึงพยายามปิดประตูให้มากที่สุด เพื่อลดโอกาสที่แฮกเกอร์มีช่องทางเข้าถึงระบบได้อย่างง่ายดาย

บทความที่เกี่ยวข้อง