ทำไมเราถึงควรกลับมาใช้ Cookie แทนการส่ง JWT Token ผ่าน Header

บทความนี้เขียนจากความเห็นส่วนตัว โปรดใช้ 🚲 ในการอ่าน
Token ในบทความนี้ขอพูดถึง Token ที่เป็น Signature-based เช่น JWT นะ

เวลาอ่านเรื่อง Token-based Authentication (ที่เป็น JWT) จะเจอข้อดีต่าง ๆ มากมาย ที่มันแก้ปัญหาที่เกิดจากการใช้ Cookie ได้ (จริงหรอ ? 😮) มาดูกันว่าข้อดีของ Token-based (JWT) นั้นมีอะไรกันบ้าง แล้วถ้าเราจะใช้ Cookie หล่ะจะทำยังไง ?


1. Token เป็นระบบ Stateless ไม่ต้องเก็บ data ฝั่ง server

จริง ๆ Cookie ก็ทำแบบ Stateless ได้เหมือนกัน ก็เอา data มา encrypt แล้วก็เก็บเป็น cookie ไง…
ซึ่ง library ที่จัดการ session แทบทุกตัว จะ support feature นี้อยู่แล้ว

2. Token เวลาจะ Logout ก็แค่ลบ Token ฝั่ง Client ไม่ต้องคุยกับ Server

Token เวลา Logout ยังไงก็ต้องคุยกับ server เพื่อ revoke refresh token ออก ถ้าแค่ลบ token ออกจาก client มันจะเป็นการ logout ได้ยังไง ถ้ามีคนก็อป token ออกไปได้ ?

ถ้าคิดแบบนี้แสดงว่า implement ระบบ Token (JWT) ผิด ไม่ได้ทำ Refresh Token ที่เป็น Stateful (Refresh Token ไม่จำเป็นที่จะต้องใช้ JWT เพราะยังไงก็เป็น Stateful อยู่แล้ว)

3. เร็วกว่า Cookie เพราะว่าไม่ต้อง query ที่ database

ถ้าเราทำ cookie แบบ stateless ก็ไม่ต่างกัน
แต่ถ้าเก็บ data ผ่าน token/cookie ก็เปลือง bandwidth แทน 🙈

ถ้ากลัวช้าเราก็ใช้ in-memory database เช่น redis หรือ memcache มาเก็บ session ก็ได้ ปกติ library ที่จัดการ session (ทุกตัวเลยก็ว่าได้) จะ support redis/memcache อยู่แล้ว

4. ใช้ Token (JWT) Scale ง่ายกว่า

จริง ๆ Cookie ก็ scale ได้นะ ถ้าไม่เก็บ session ใน memory/file ไปเก็บใน database แทน

5. ใช้ Token ไม่ต้องกลัว CSRF

แต่อย่าลืม XSS นะ 😛

บางคนก็บอกว่า งั้นก็เอา Token เก็บใน Cookie แทน Local Storage สิ… แต่ถึงจะเก็บ Token ใน Cookie ยังไงเราก็ต้องดึงออกมาใช้ฝั่ง Client อยู่ดี ก็ไม่ต่างอะไรกับ เก็บใน Local Storage เพราะเราใส่ HttpOnly ไม่ได้

6. Token ใช้กับ Mobile ได้เลย

แล้วมันต่างอะไรกับ Cookie ? เพราะ Cookie มันก็ส่งมาใน header ก็อ่านจาก header แทนสิ…

นอกจากว่าเราจะทำ API ให้ Mobile โดยเฉพาะ ซึ่งเราสามารถใช้ Stateful Token (ที่ไม่ใช่ JWT) ได้

7. Token ส่ง Cross Origin Request ง่ายกว่า Cookie

อันนี้น่าจะเป็นข้อเสียของ Cookie ถ้าเราทำ Micro-services แล้วแยก origin กัน แต่ปกติแล้วถ้าทำ micro-services ยังไงก็ต้องส่ง request ผ่าน API Gateway อยู่แล้ว ก็ให้ API Gateway จัดการ Cookie ให้สิ ?

บางคนอาจจะบอกว่า เว็บเราอยู่ที่ example.com แต่ api อยู่ที่ api.example.com เวลาส่ง request ไป cookie มันไม่ไปด้วย… แสดงว่าเราน่าจะ config CORS ผิด ลืมใส่ Access-Control-Allow-Credentials รึเปล่า ?


แล้วถ้าเราจะใช้ Cookie มันมีข้อดีอะไรบ้าง

1. Implement ง่าย

เพราะว่า library/framework ส่วนใหญ่จะ support feature นี้อยู่แล้ว ถ้าทำ Token อาจจะต้องเขียนเอง

2. ไม่ต้องปวดหัวว่า Payload ใน Token จะ Stale

เช่น

  • User ได้ revoke Refresh Token แล้ว แต่ Access Token ยังไม่หมดอายุ
  • User ถูกระบบ Ban แล้ว แต่ Access Token ยังไม่หมดอายุ
  • User ถูกลดสิทธิ์แล้ว แต่ Access Token ยังมีสิทธิ์อยู่

3. ประหยัด Request ไปได้ 1 Request

ไม่ต้องส่ง Request ไปขอ Access Token ทุกครั้ง หรือเราตั้งเวลาให้ Access Token ใช้ได้นานมาก ๆ ? 😝

Access Token จริง ๆ ควรเป็น One-Time Token ใช้ได้แค่ครั้งเดียว


แล้ว JWT จะใช้ตอนไหน หล่ะ ??

มันคงต้องมีประโยชน์บ้างหล่ะ… ไม่งั้นเขาจะคิดมาทำไม…
ก็ Server-Server Communication ไง

JWT เป็น Signature-based Authentication หมายความว่า เราสามารถเช็คว่า JWT ตัวนี้ valid ไหม ผ่าน Signature

เช่น

  • เก็บ Private Key ไว้ที่ Server A
  • เก็บ Public Key ไว้ที่ Server B
  • Server A จะคุยกับ Server B, Server A ก็สร้าง JWT โดยใช้ Private Key
  • Server B ใช้ Public Key มา Verify JWT ว่า Valid ไหม

จะเห็นว่า เราไม่ต้องทำ Refresh/Access Token เลย เพราะ Access Token สามารถสร้างจาก Server A ได้เลย โดนที่ไม่ต้องมี Refresh Token ด้วยซ้ำ
และ Access Token จะเป็น One-Time Token เราสามารถตั้งเวลาหมดอายุสั้น ๆ (เช่น 1 นาที) เพื่อให้ Token สามารถใช้ได้แค่ครั้งเดียว

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.