OAuth 2.0 และ JWT Authentication คู่มือครบถ้วน

ในโลกดิจิทัลที่ขับเคลื่อนด้วยแอปพลิเคชันและบริการออนไลน์ การรักษาความปลอดภัยของข้อมูลผู้ใช้เป็นสิ่งสำคัญยิ่งครับ ไม่ว่าจะเป็นการเข้าสู่ระบบเว็บไซต์ที่คุณชื่นชอบ การเชื่อมต่อแอปพลิเคชันหนึ่งเข้ากับอีกแอปพลิเคชันหนึ่ง หรือแม้แต่การเข้าถึง API ต่างๆ เบื้องหลังความสะดวกสบายเหล่านี้ล้วนมีเทคโนโลยีด้านความปลอดภัยที่ซับซ้อนทำงานอยู่ และสองในมาตรฐานที่ทรงพลังและได้รับการยอมรับมากที่สุดในปัจจุบันคือ OAuth 2.0 สำหรับการอนุญาต (Authorization) และ JWT (JSON Web Tokens) สำหรับการยืนยันตัวตน (Authentication) แบบไร้สถานะ (Stateless) ครับ

บทความนี้ SiamLancard.com จะพาคุณดำดิ่งสู่โลกของ OAuth 2.0 และ JWT ตั้งแต่พื้นฐาน แนวคิดหลัก การทำงานร่วมกัน ไปจนถึงแนวทางการนำไปใช้งานจริงอย่างละเอียด พร้อมทั้งคำแนะนำด้านความปลอดภัย เพื่อให้คุณเข้าใจและสามารถประยุกต์ใช้เทคโนโลยีเหล่านี้ได้อย่างมั่นใจและมีประสิทธิภาพครับ

ทำความเข้าใจกับการยืนยันตัวตนและการอนุญาต (Authentication & Authorization)

ก่อนที่เราจะเจาะลึกถึง OAuth 2.0 และ JWT เรามาทำความเข้าใจแนวคิดพื้นฐานสองอย่างที่มักจะถูกใช้สลับกันหรือสับสนกันอยู่บ่อยครั้ง นั่นคือ Authentication และ Authorization ครับ การแยกความแตกต่างของสองสิ่งนี้เป็นก้าวแรกที่สำคัญในการทำความเข้าใจระบบความปลอดภัยสมัยใหม่

Authentication (การยืนยันตัวตน) คืออะไร?

Authentication คือกระบวนการพิสูจน์ว่าผู้ใช้งานหรือระบบกำลังอ้างว่าเป็นใคร “คุณเป็นคนที่คุณอ้างว่าเป็นจริงหรือไม่?” นั่นคือคำถามหลักของการ Authentication ครับ โดยทั่วไปแล้ว กระบวนการนี้มักเกี่ยวข้องกับการให้ข้อมูลประจำตัว (Credentials) เช่น ชื่อผู้ใช้และรหัสผ่าน หรืออาจจะเป็นวิธีการที่ซับซ้อนขึ้น เช่น การใช้ลายนิ้วมือ ใบหน้า หรือรหัส OTP (One-Time Password) ครับ

  • ตัวอย่าง: คุณเข้าสู่ระบบ Facebook ด้วยอีเมลและรหัสผ่าน ระบบจะตรวจสอบว่าข้อมูลที่คุณป้อนถูกต้องหรือไม่ หากถูกต้อง คุณก็จะถูกยืนยันตัวตนว่าเป็นเจ้าของบัญชีนั้นๆ ครับ

Authorization (การอนุญาต) คืออะไร?

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

  • ตัวอย่าง: คุณเข้าสู่ระบบ Facebook (Authentication สำเร็จ) จากนั้นคุณต้องการโพสต์รูปภาพลงในหน้า Timeline ของคุณ ระบบจะตรวจสอบว่าคุณมีสิทธิ์ในการโพสต์ (Authorization) หรือไม่ แน่นอนว่าคุณมีสิทธิ์ เพราะเป็นเจ้าของบัญชี แต่ถ้าคุณพยายามจะโพสต์ลงบนหน้า Timeline ของเพื่อนโดยที่เพื่อนไม่ได้อนุญาต คุณก็จะทำไม่ได้ครับ
  • อีกตัวอย่าง: แอปพลิเคชันรูปภาพต้องการเข้าถึงรูปภาพของคุณบน Google Photos ระบบ Google Photos จะต้องได้รับ การอนุญาต จากคุณก่อน (Authorization) เพื่อให้แอปนั้นเข้าถึงข้อมูลได้ แม้ว่าคุณจะเข้าสู่ระบบ Google ของคุณแล้วก็ตาม

ทำไมสองสิ่งนี้ถึงสำคัญ?

ทั้ง Authentication และ Authorization เป็นรากฐานสำคัญของความปลอดภัยในระบบคอมพิวเตอร์ครับ การรวมกันของสองสิ่งนี้ช่วยให้ระบบสามารถ:

  • ปกป้องข้อมูลส่วนตัวและทรัพยากรที่มีค่า
  • ควบคุมการเข้าถึงและจำกัดการกระทำของผู้ใช้
  • รักษาความสมบูรณ์และความลับของข้อมูล

ในหลายๆ กรณี ระบบจะทำการ Authentication ก่อนเสมอ จากนั้นจึงตามด้วย Authorization ครับ

เจาะลึก OAuth 2.0: มาตรฐานแห่งการอนุญาต

OAuth 2.0 เป็นมาตรฐานอุตสาหกรรมสำหรับการอนุญาต (Authorization) ที่ช่วยให้แอปพลิเคชันหนึ่ง (Client) สามารถเข้าถึงทรัพยากรของผู้ใช้บนบริการอื่น (Resource Server) ได้โดยไม่ต้องให้ Client รู้ข้อมูลประจำตัว (Credentials) ของผู้ใช้นั้นๆ ครับ พูดง่ายๆ คือมันเป็นวิธีที่ปลอดภัยในการให้ “กุญแจชั่วคราว” แก่แอปพลิเคชัน เพื่อให้มันไปเปิดประตูข้อมูลบางส่วนให้คุณ โดยที่คุณยังคงเป็นเจ้าของกุญแจหลักและควบคุมการเข้าถึงได้ทั้งหมดครับ

OAuth 2.0 คืออะไร? (ไม่ใช่ Authentication!)

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

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

บทบาทสำคัญใน OAuth 2.0

ในการทำความเข้าใจ OAuth 2.0 เราต้องรู้จักบทบาทหลัก 4 ประการนี้ครับ

  1. Resource Owner (เจ้าของทรัพยากร): คือผู้ใช้งาน เช่น คุณเอง ที่เป็นเจ้าของข้อมูลหรือทรัพยากรที่ต้องการให้แอปพลิเคชันอื่นเข้าถึง

    ตัวอย่าง: คุณที่มีรูปภาพบน Google Photos
  2. Client (แอปพลิเคชัน): คือแอปพลิเคชันที่ต้องการเข้าถึงทรัพยากรของผู้ใช้

    ตัวอย่าง: แอปพลิเคชันแต่งรูปภาพที่คุณติดตั้งบนมือถือ
  3. Authorization Server (เซิร์ฟเวอร์อนุญาต): คือเซิร์ฟเวอร์ที่ทำหน้าที่ยืนยันตัวตนของ Resource Owner และออก Access Token ให้กับ Client หลังจากที่ Resource Owner ได้อนุญาตแล้ว

    ตัวอย่าง: เซิร์ฟเวอร์ OAuth ของ Google
  4. Resource Server (เซิร์ฟเวอร์ทรัพยากร): คือเซิร์ฟเวอร์ที่เก็บข้อมูลหรือทรัพยากรของผู้ใช้ และอนุญาตให้ Client เข้าถึงข้อมูลได้โดยใช้ Access Token ที่ได้รับมา

    ตัวอย่าง: เซิร์ฟเวอร์ Google Photos API

Access Token และ Refresh Token

หัวใจสำคัญของ OAuth 2.0 คือ Access Token ครับ

  • Access Token: เป็นสตริงที่เข้ารหัสซึ่งเป็นเหมือน “บัตรผ่าน” หรือ “กุญแจชั่วคราว” ที่ Client ใช้ในการเรียก API ของ Resource Server เพื่อเข้าถึงทรัพยากรของผู้ใช้ Access Token มีอายุการใช้งานจำกัด (มักจะสั้น) เพื่อเพิ่มความปลอดภัย และสามารถมี “Scopes” (สิทธิ์) ที่กำหนดไว้ได้ เช่น สิทธิ์ในการอ่านรูปภาพเท่านั้น หรือสิทธิ์ในการโพสต์ข้อความเท่านั้นครับ
  • Refresh Token: เมื่อ Access Token หมดอายุ Client สามารถใช้ Refresh Token เพื่อขอ Access Token ใหม่จาก Authorization Server ได้โดยไม่ต้องให้ผู้ใช้ต้องล็อกอินใหม่หรือให้การอนุญาตซ้ำอีกครั้งครับ Refresh Token มักจะมีอายุการใช้งานที่ยาวนานกว่า Access Token และควรเก็บรักษาไว้อย่างปลอดภัยสูงสุดครับ

Grant Types (Flows): รูปแบบการอนุญาตที่หลากหลาย

OAuth 2.0 มีรูปแบบการทำงานที่เรียกว่า “Grant Types” หรือ “Flows” ซึ่งแต่ละแบบก็ถูกออกแบบมาให้เหมาะกับประเภทของ Client และสถานการณ์การใช้งานที่แตกต่างกันไปครับ

1. Authorization Code Grant (พร้อม PKCE)

นี่คือ Grant Type ที่นิยมใช้มากที่สุดและปลอดภัยที่สุดสำหรับแอปพลิเคชันบนเว็บ (Web Applications) และแอปพลิเคชันมือถือ/SPA (Single Page Applications) ครับ

หลักการทำงาน:

  1. Client (แอปพลิเคชันของคุณ) พาผู้ใช้ไปยังหน้าล็อกอินและขออนุญาตของ Authorization Server (เช่น Google, Facebook).
  2. Resource Owner (ผู้ใช้) ล็อกอินและให้สิทธิ์แก่ Client.
  3. Authorization Server ส่ง Authorization Code กลับไปยัง Client (ผ่าน Redirect URL).
  4. Client ส่ง Authorization Code ที่ได้รับมา พร้อมกับ Client ID และ Client Secret (ถ้ามี) ไปยัง Authorization Server เพื่อแลกเป็น Access Token และ Refresh Token (ในกรณีของเว็บแอปพลิเคชัน Client Secret จะช่วยให้การแลกเปลี่ยนนี้ปลอดภัยยิ่งขึ้น).
  5. Authorization Server ตรวจสอบความถูกต้องและส่ง Access Token และ Refresh Token กลับไปให้ Client.
  6. Client ใช้ Access Token ในการเรียก API ของ Resource Server เพื่อเข้าถึงข้อมูลของผู้ใช้.

สำหรับแอปพลิเคชันที่ไม่มีความลับ (Public Clients) เช่น แอปพลิเคชันมือถือ หรือ Single Page Applications (SPA) การใช้ PKCE (Proof Key for Code Exchange) เป็นสิ่งสำคัญมากครับ PKCE เพิ่มความปลอดภัยโดยการเพิ่มพารามิเตอร์ code_challenge และ code_verifier เพื่อป้องกันการดักจับ Authorization Code กลางทาง และนำไปใช้โดยแอปพลิเคชันที่ไม่ได้รับอนุญาตครับ

อ่านเพิ่มเติมเกี่ยวกับการทำงานของ PKCE

2. Client Credentials Grant

Grant Type นี้ใช้สำหรับการอนุญาตแบบ Machine-to-Machine หรือแอปพลิเคชันที่ต้องการเข้าถึงทรัพยากรของตนเอง ไม่ใช่ทรัพยากรของผู้ใช้ครับ ไม่มี Resource Owner เข้ามาเกี่ยวข้อง

หลักการทำงาน:

  1. Client (แอปพลิเคชัน) ส่ง Client ID และ Client Secret ไปยัง Authorization Server โดยตรง.
  2. Authorization Server ตรวจสอบความถูกต้องและส่ง Access Token กลับไปให้ Client.
  3. Client ใช้ Access Token ในการเรียก API ของ Resource Server.

ตัวอย่าง: บริการไมโครเซอร์วิสหนึ่งต้องการเรียก API ของอีกไมโครเซอร์วิสหนึ่งภายในระบบเดียวกัน

3. Resource Owner Password Credentials Grant (ไม่แนะนำ)

Grant Type นี้อนุญาตให้ Client ขอ Access Token โดยตรงจาก Authorization Server โดยใช้ชื่อผู้ใช้และรหัสผ่านของผู้ใช้ (Resource Owner) ครับ

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

4. Implicit Grant (เลิกใช้งานแล้ว)

Grant Type นี้เคยใช้สำหรับแอปพลิเคชันที่ทำงานในเบราว์เซอร์ (เช่น Single Page Applications) โดย Authorization Server จะส่ง Access Token กลับมาใน URL fragment โดยตรง

ข้อควรระวัง: Implicit Grant ถูกพิจารณาว่าไม่ปลอดภัยแล้วครับ เนื่องจาก Access Token อาจถูกดักจับได้ง่ายจากประวัติเบราว์เซอร์หรือ Referer Header และไม่มี Refresh Token มาให้ใช้งาน ทำให้ผู้ใช้ต้องล็อกอินบ่อยครั้งครับ ไม่ควรใช้ Grant Type นี้อีกต่อไป และควรหันไปใช้ Authorization Code Grant พร้อม PKCE แทนครับ

Scopes: การควบคุมสิทธิ์อย่างละเอียด

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

  • ตัวอย่าง: หากคุณเชื่อมต่อแอปพลิเคชันแต่งรูปภาพกับ Google Photos คุณอาจจะให้สิทธิ์แค่ read_photos (อ่านรูปภาพ) หรือ upload_photos (อัปโหลดรูปภาพ) แต่ไม่ใช่ delete_photos (ลบรูปภาพ) ซึ่งช่วยให้ผู้ใช้ควบคุมข้อมูลของตนเองได้อย่างละเอียดครับ

เมื่อไหร่ที่ควรใช้ OAuth 2.0?

OAuth 2.0 เหมาะสมอย่างยิ่งสำหรับสถานการณ์ต่อไปนี้:

  • เมื่อคุณต้องการให้แอปพลิเคชันภายนอกเข้าถึงข้อมูลของผู้ใช้จากบริการของคุณ (เช่น “Login with Google”, “Login with Facebook”).
  • เมื่อแอปพลิเคชันของคุณต้องการเข้าถึงข้อมูลของผู้ใช้จากบริการภายนอก (เช่น แอปพลิเคชันจัดการโปรเจกต์ต้องการเข้าถึงไฟล์บน Google Drive ของผู้ใช้).
  • เมื่อคุณต้องการสร้าง API ที่ต้องการการอนุญาตสำหรับ Client ประเภทต่างๆ (Web, Mobile, Desktop).

ข้อควรพิจารณาด้านความปลอดภัยของ OAuth 2.0

  • ใช้ HTTPS/TLS เสมอ: การสื่อสารทั้งหมดระหว่าง Client, Authorization Server และ Resource Server ควรผ่าน HTTPS เพื่อเข้ารหัสข้อมูลและป้องกันการดักจับข้อมูล.
  • ใช้ PKCE: สำหรับ Public Clients (Mobile Apps, SPAs) เพื่อป้องกัน Code Interception Attack.
  • ตรวจสอบ Redirect URI: Authorization Server ควรตรวจสอบ Redirect URI ที่ลงทะเบียนไว้กับ Client อย่างเคร่งครัด เพื่อป้องกันการโจมตีแบบ Open Redirect.
  • จัดการ Client Secret อย่างปลอดภัย: สำหรับ Confidential Clients (Web Apps ที่รันบนเซิร์ฟเวอร์) Client Secret ควรเก็บไว้เป็นความลับสูงสุดและไม่ควรเปิดเผยสู่สาธารณะ.
  • จำกัด Scope: ขอสิทธิ์เท่าที่จำเป็นสำหรับ Client เท่านั้น เพื่อลดความเสี่ยงหาก Client ถูกบุกรุก.
  • ทำให้ Access Token มีอายุสั้น: และใช้ Refresh Token เพื่อขอ Access Token ใหม่ เพื่อลดระยะเวลาที่โทเค็นที่ถูกขโมยจะใช้งานได้.

JWT (JSON Web Tokens): หัวใจของการยืนยันตัวตนแบบไร้สถานะ

หลังจากที่เราเข้าใจ OAuth 2.0 ในฐานะโปรโตคอลการอนุญาตแล้ว ทีนี้เรามาทำความรู้จักกับ JWT ซึ่งมักจะถูกนำมาใช้เป็นรูปแบบของ Access Token ใน OAuth 2.0 และยังเป็นมาตรฐานสำคัญสำหรับการยืนยันตัวตนแบบไร้สถานะในยุคปัจจุบันครับ

JWT คืออะไร?

JWT (JSON Web Token) คือมาตรฐาน RFC 7519 ที่กำหนดวิธีการส่งข้อมูลระหว่างสองฝ่ายอย่างปลอดภัยในรูปแบบ JSON ครับ ข้อมูลที่ถูกส่งจะได้รับการเข้ารหัสและลงชื่อด้วยลายเซ็นดิจิทัล ทำให้มั่นใจได้ว่าข้อมูลนั้นไม่ได้ถูกเปลี่ยนแปลงระหว่างทาง และมาจากผู้ส่งที่เชื่อถือได้ครับ

สิ่งสำคัญคือ JWT เป็น Stateless หรือไร้สถานะ นั่นหมายความว่า เซิร์ฟเวอร์ไม่จำเป็นต้องเก็บข้อมูล Session ของผู้ใช้แต่ละคนไว้ ข้อมูลทั้งหมดที่จำเป็นสำหรับการยืนยันตัวตนและการอนุญาตจะถูกบรรจุอยู่ในตัว Token เอง ทำให้เหมาะมากสำหรับระบบที่ต้องการความสามารถในการขยายขนาด (Scalability) เช่น Microservices หรือ API Gateways ครับ

โครงสร้างของ JWT: Header, Payload, Signature

JWT ประกอบด้วย 3 ส่วนหลักๆ ที่คั่นด้วยเครื่องหมายจุด (.) เมื่อเข้ารหัส Base64 ครับ

xxxxxxxx.yyyyyyyy.zzzzzzzz

โดยที่:

  • xxxxxxxx คือ Header
  • yyyyyyyy คือ Payload
  • zzzzzzzz คือ Signature

1. Header

ส่วน Header มักจะเป็นวัตถุ JSON ที่ประกอบด้วยข้อมูลเกี่ยวกับประเภทของ Token และอัลกอริทึมการเข้ารหัสที่ใช้ในการสร้าง Signature ครับ

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg (Algorithm): ระบุอัลกอริทึมที่ใช้ในการสร้าง Signature เช่น HS256 (HMAC SHA256) หรือ RS256 (RSA SHA256).
  • typ (Type): ระบุประเภทของ Token ซึ่งโดยทั่วไปคือ “JWT”.

JSON Object นี้จะถูกเข้ารหัสด้วย Base64 URL Safe.

2. Payload

ส่วน Payload หรือที่เรียกว่า JWT Claims เป็นวัตถุ JSON ที่บรรจุข้อมูลจริงที่ต้องการส่งครับ ข้อมูลเหล่านี้เรียกว่า “Claims” ซึ่งเป็นข้อความยืนยันเกี่ยวกับเอนทิตี (โดยทั่วไปคือผู้ใช้) และข้อมูลเพิ่มเติม

{
  "sub": "1234567890",
  "name": "Siam Lancard User",
  "admin": true,
  "iat": 1516239022,
  "exp": 1516242622
}

Claims มี 3 ประเภทหลักๆ ครับ:

  1. Registered Claims: เป็น Claims ที่ถูกกำหนดไว้ในมาตรฐาน JWT เพื่อให้สามารถทำงานร่วมกันได้ (Interoperable) แต่ไม่จำเป็นต้องมีทั้งหมดครับ

    • iss (Issuer): ผู้ที่ออก Token
    • sub (Subject): หัวข้อของ Token (มักจะเป็น User ID)
    • aud (Audience): ผู้รับ Token
    • exp (Expiration Time): เวลาหมดอายุของ Token (เป็น Unix timestamp)
    • nbf (Not Before): เวลาที่ Token จะเริ่มใช้งานได้
    • iat (Issued At): เวลาที่ Token ถูกออก
    • jti (JWT ID): รหัสเฉพาะของ Token
  2. Public Claims: เป็น Claims ที่เราสามารถกำหนดเองได้ แต่ควรตั้งชื่อให้ไม่ซ้ำกับ Registered Claims หรือใช้ URI เพื่อหลีกเลี่ยงความขัดแย้ง.
  3. Private Claims: เป็น Claims ที่กำหนดขึ้นมาเพื่อใช้ภายในแอปพลิเคชันหรือระหว่างกลุ่มที่ตกลงกันเองเท่านั้น ไม่ได้มีจุดประสงค์ให้เป็นมาตรฐานหรือ Public.

JSON Object นี้ก็จะถูกเข้ารหัสด้วย Base64 URL Safe เช่นกันครับ

3. Signature

ส่วน Signature ใช้เพื่อตรวจสอบความสมบูรณ์ของ Token ว่า Header และ Payload ไม่ได้ถูกเปลี่ยนแปลงระหว่างทางครับ Signature สร้างขึ้นโดยการนำ Header ที่เข้ารหัส, Payload ที่เข้ารหัส และคีย์ลับ (Secret Key) มารวมกัน แล้วทำการแฮชด้วยอัลกอริทึมที่ระบุใน Header

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

ความสำคัญของ Signature: หากมีใครพยายามแก้ไข Header หรือ Payload ของ Token โดยที่ไม่มีคีย์ลับ การสร้าง Signature ใหม่ก็จะทำไม่ได้ และเมื่อเซิร์ฟเวอร์ตรวจสอบ Signature ด้วยคีย์ลับของตัวเอง ก็จะพบว่า Signature ไม่ถูกต้อง และปฏิเสธ Token นั้นทันทีครับ

JWT ทำงานอย่างไร: การยืนยันตัวตนแบบ Stateless

เมื่อผู้ใช้ล็อกอินสำเร็จ (ผ่านกระบวนการ Authentication เช่น ชื่อผู้ใช้/รหัสผ่าน) เซิร์ฟเวอร์จะสร้าง JWT ที่มีข้อมูลประจำตัวของผู้ใช้ (เช่น User ID, บทบาท) และส่งกลับไปให้ Client ครับ

  1. Client (เช่น เบราว์เซอร์, แอปพลิเคชันมือถือ) จะเก็บ JWT นี้ไว้ (มักจะเก็บใน Local Storage, Session Storage หรือ HTTP-only Cookie).
  2. เมื่อ Client ต้องการเข้าถึงทรัพยากรที่ต้องได้รับการยืนยันตัวตน (Protected Resource) Client จะส่ง JWT กลับไปยัง Server ใน Header ของ HTTP Request (โดยทั่วไปคือ Authorization: Bearer <token>).
  3. Server จะรับ JWT มา ตรวจสอบ Signature โดยใช้คีย์ลับที่ตัวเองมี หาก Signature ถูกต้อง Server ก็จะมั่นใจได้ว่า Token นี้มาจากผู้ส่งที่เชื่อถือได้และไม่ได้ถูกแก้ไข.
  4. จากนั้น Server จะอ่านข้อมูลใน Payload เพื่อยืนยันตัวตนของผู้ใช้และตรวจสอบสิทธิ์ (Authorization) ตามข้อมูลที่อยู่ใน Token.
  5. หากทุกอย่างถูกต้อง Server ก็จะประมวลผลคำขอและส่งข้อมูลกลับไปให้ Client ครับ.

Stateless: เซิร์ฟเวอร์ไม่จำเป็นต้องเก็บ Session ID หรือสถานะของผู้ใช้ไว้ในหน่วยความจำ เพราะข้อมูลทั้งหมดอยู่ใน JWT แล้ว ทำให้สามารถขยายขนาดระบบได้ง่ายขึ้นครับ

ข้อดีและข้อเสียของ JWT

ข้อดี:

  • Statelessness: ลดภาระของเซิร์ฟเวอร์ ไม่ต้องเก็บ Session State ทำให้ขยายขนาดระบบได้ง่าย.
  • Compactness: JWT มีขนาดเล็ก เหมาะสำหรับการส่งผ่าน URL, POST parameter หรือ HTTP header.
  • Self-contained: ข้อมูลทั้งหมดที่จำเป็นอยู่ในตัว Token ทำให้ลดจำนวนการเรียกฐานข้อมูล.
  • Security: ด้วย Signature ทำให้มั่นใจในความสมบูรณ์และที่มาของข้อมูล.
  • Cross-domain: ใช้งานได้ดีในสถาปัตยกรรม Microservices หรือเมื่อ Client และ Resource Server อยู่คนละโดเมน.

ข้อเสีย:

  • ขนาดใหญ่กว่า Session ID: หากใส่ข้อมูลมากเกินไปใน Payload อาจทำให้ Token มีขนาดใหญ่ขึ้น.
  • ไม่มีกลไกการเพิกถอนในตัว (Revocation): เมื่อ JWT ถูกออกไปแล้ว ตราบใดที่ยังไม่หมดอายุ ก็จะยังคงใช้งานได้ เว้นแต่จะมีการนำ Blacklist มาใช้ (ซึ่งจะทำให้สูญเสียความเป็น Stateless ไปบางส่วน).
  • เสี่ยงต่อ XSS: หากเก็บ JWT ไว้ใน Local Storage และถูกโจมตีด้วย XSS attacker อาจขโมย Token ไปใช้ได้.
  • ข้อมูลใน Payload ไม่เป็นความลับ: ข้อมูลใน Payload สามารถถอดรหัส Base64 ออกมาอ่านได้ง่าย ดังนั้นจึงไม่ควรใส่ข้อมูลที่อ่อนไหวมากๆ ลงไปใน Payload ครับ

เมื่อไหร่ที่ควรใช้ JWT?

  • API Authentication: เหมาะสำหรับ RESTful APIs ที่ต้องการการยืนยันตัวตนแบบ Stateless.
  • Single Page Applications (SPAs): ที่ต้องการสื่อสารกับ Backend API.
  • Microservices: สำหรับการยืนยันตัวตนและการอนุญาตระหว่างบริการต่างๆ.
  • OAuth 2.0 Access Tokens: JWT มักถูกใช้เป็นรูปแบบของ Access Token ใน OAuth 2.0 (และ ID Token ใน OpenID Connect).

อ่านเพิ่มเติมเกี่ยวกับ JWT และการใช้งาน

ตัวอย่างการสร้างและตรวจสอบ JWT (Python)

นี่คือตัวอย่างง่ายๆ ของการสร้างและตรวจสอบ JWT โดยใช้ไลบรารี PyJWT ใน Python ครับ

import jwt
import datetime
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError

# --- กำหนดคีย์ลับ (Secret Key) ---
# ในการใช้งานจริง ควรเก็บคีย์นี้ไว้ในตัวแปรสภาพแวดล้อม (environment variable)
# หรือระบบจัดการ Secret อย่างปลอดภัย ห้าม hardcode!
SECRET_KEY = "your-super-secret-key-that-no-one-should-know"

# --- 1. การสร้าง JWT ---
def create_jwt(user_id: str, username: str, is_admin: bool = False, expires_in_minutes: int = 30):
    """สร้าง JWT พร้อมข้อมูลผู้ใช้และเวลาหมดอายุ"""
    payload = {
        "user_id": user_id,
        "username": username,
        "is_admin": is_admin,
        "exp": datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=expires_in_minutes),
        "iat": datetime.datetime.now(datetime.timezone.utc)
    }
    # เข้ารหัส JWT ด้วย HS256 และคีย์ลับ
    encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
    return encoded_jwt

# --- 2. การตรวจสอบและถอดรหัส JWT ---
def verify_jwt(token: str):
    """ตรวจสอบความถูกต้องและถอดรหัส JWT"""
    try:
        decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        print(f"Token ถูกต้องและถอดรหัสได้: {decoded_payload}")
        return decoded_payload
    except ExpiredSignatureError:
        print("ข้อผิดพลาด: Token หมดอายุแล้วครับ")
        return None
    except InvalidTokenError:
        print("ข้อผิดพลาด: Token ไม่ถูกต้องหรือไม่สามารถถอดรหัสได้ครับ")
        return None
    except Exception as e:
        print(f"ข้อผิดพลาดที่ไม่คาดคิดในการตรวจสอบ Token: {e}")
        return None

# --- ตัวอย่างการใช้งานจริง ---
if __name__ == "__main__":
    print("--- สร้าง JWT ---")
    user_token = create_jwt("user123", "Alice", is_admin=False, expires_in_minutes=1)
    admin_token = create_jwt("admin456", "Bob_Admin", is_admin=True, expires_in_minutes=5)

    print(f"User Token: {user_token}")
    print(f"Admin Token: {admin_token}")

    print("\n--- ตรวจสอบ User Token ---")
    user_data = verify_jwt(user_token)
    if user_data:
        print(f"User ID: {user_data.get('user_id')}, Username: {user_data.get('username')}, Admin: {user_data.get('is_admin')}")

    print("\n--- ตรวจสอบ Admin Token ---")
    admin_data = verify_jwt(admin_token)
    if admin_data:
        print(f"User ID: {admin_data.get('user_id')}, Username: {admin_data.get('username')}, Admin: {admin_data.get('is_admin')}")

    # ตัวอย่าง Token หมดอายุ (รอ 1 นาที)
    print("\n--- รอให้ User Token หมดอายุ (ประมาณ 1 นาที) ---")
    # import time
    # time.sleep(65) # Uncomment เพื่อทดสอบ Token หมดอายุ

    # print("\n--- ตรวจสอบ User Token อีกครั้งหลังหมดอายุ ---")
    # expired_user_data = verify_jwt(user_token)
    # if expired_user_data:
    #     print("User Token ยังใช้งานได้ (ไม่ควรเกิดขึ้นหากหมดอายุ)")
    # else:
    #     print("User Token หมดอายุแล้วตามที่คาดไว้ครับ")

    # ตัวอย่าง Token ปลอมแปลง (แก้ไขบางส่วน)
    print("\n--- ตรวจสอบ Token ที่ถูกปลอมแปลง ---")
    # ลองแก้ไขส่วน payload ของ token user_token
    # โดยทั่วไปแล้ว การแก้ไขเพียงบางส่วนของ token จะทำให้ signature ไม่ตรง
    # แต่ถ้า attacker สามารถคำนวณ signature ใหม่ได้ด้วย secret key จะถือว่า token ถูกต้อง
    # นี่คือเหตุผลที่ secret key ต้องเป็นความลับสูงสุด!
    
    # สมมติว่ามีคนพยายามแก้ไข payload แต่ไม่มี secret key
    parts = user_token.split('.')
    fake_payload_base64 = jwt.base64url_encode(b'{"user_id": "hacker123", "username": "Hacker", "is_admin": true, "exp": 2000000000, "iat": 1516239022}').decode('utf-8')
    tampered_token = f"{parts[0]}.{fake_payload_base64}.{parts[2]}" # Signature ยังคงเป็นของเดิม
    
    print(f"Tampered Token: {tampered_token}")
    tampered_data = verify_jwt(tampered_token)
    if not tampered_data:
        print("Token ถูกปลอมแปลงและไม่ผ่านการตรวจสอบลายเซ็นครับ")

การทำงานร่วมกัน: OAuth 2.0 และ JWT Authentication

บ่อยครั้งที่เราจะเห็น OAuth 2.0 และ JWT ถูกพูดถึงในบริบทเดียวกัน และนั่นเป็นเพราะทั้งสองมาตรฐานนี้ทำงานร่วมกันได้ดีมากครับ แต่มีบทบาทที่แตกต่างกัน

OAuth 2.0 มอบสิทธิ์, JWT ยืนยันตัวตน

ลองนึกภาพว่า OAuth 2.0 คือกระบวนการทั้งหมดที่ Client (แอปพลิเคชัน) ใช้เพื่อขอสิทธิ์จาก Resource Owner (ผู้ใช้) ในการเข้าถึงทรัพยากรบน Resource Server ครับ ผลลัพธ์สุดท้ายของกระบวนการ OAuth 2.0 คือการที่ Client ได้รับ Access Token

และในหลายๆ กรณี Access Token นี้เองที่อยู่ในรูปแบบของ JWT ครับ

เมื่อ Client ได้รับ Access Token (ที่เป็น JWT) มาแล้ว Client จะใช้ JWT นั้นส่งไปพร้อมกับทุกคำขอ API ไปยัง Resource Server ใน Header Authorization: Bearer <JWT> ครับ Resource Server ก็จะทำการตรวจสอบ JWT นั้น (ตามที่เราได้อธิบายไปในส่วนของ JWT) เพื่อ:

  1. ยืนยันว่า Client ที่ส่งคำขอนี้เป็นใคร (Authentication).
  2. ตรวจสอบว่า Client มีสิทธิ์เข้าถึงทรัพยากรที่ร้องขอหรือไม่ (Authorization) โดยดูจากข้อมูลใน Payload ของ JWT และ Scope ที่ได้รับอนุญาต.

ดังนั้น โดยสรุปคือ OAuth 2.0 เป็นกลไกในการ มอบ Access Token (ซึ่งอาจเป็น JWT) ให้กับ Client ในขณะที่ JWT เป็น รูปแบบ ของ Access Token ที่ Client ใช้เพื่อ ยืนยันตัวตนและแสดงสิทธิ์ กับ Resource Server ครับ

OpenID Connect (OIDC): การยืนยันตัวตนบน OAuth 2.0

อย่างที่เราทราบกันว่า OAuth 2.0 ไม่ได้มีไว้สำหรับการยืนยันตัวตนโดยตรง แต่ในทางปฏิบัติ ผู้ใช้มักต้องการยืนยันตัวตนของตนเองเมื่อเข้าสู่ระบบผ่านบริการภายนอก เช่น “Login with Google” ครับ

นี่คือจุดที่ OpenID Connect (OIDC) เข้ามามีบทบาทครับ OIDC เป็นเลเยอร์สำหรับการยืนยันตัวตนที่สร้างขึ้นบน OAuth 2.0 ครับ OIDC เพิ่มความสามารถในการยืนยันตัวตนของผู้ใช้เข้ามา โดยการออก ID Token ซึ่งเป็น JWT อีกประเภทหนึ่ง

  • ID Token (JWT): เมื่อผู้ใช้ล็อกอินและให้สิทธิ์ผ่าน OIDC Authorization Server นอกเหนือจาก Access Token แล้ว Client จะได้รับ ID Token กลับมาด้วย ID Token นี้เป็น JWT ที่มีข้อมูลเกี่ยวกับผู้ใช้ (เช่น User ID, ชื่อ, อีเมล) ที่ได้รับการยืนยันตัวตนแล้วครับ Client สามารถใช้ ID Token นี้เพื่อยืนยันตัวตนของผู้ใช้ได้ทันทีโดยไม่ต้องเรียก API เพิ่มเติมครับ

ดังนั้น ในระบบที่ต้องการทั้งการอนุญาต (OAuth 2.0) และการยืนยันตัวตน (OIDC) เรามักจะเห็น JWT ถูกใช้ในสองบทบาท:

  1. เป็น ID Token เพื่อยืนยันตัวตนของผู้ใช้.
  2. เป็น Access Token เพื่ออนุญาตให้ Client เข้าถึงทรัพยากรของผู้ใช้.

เปรียบเทียบ: Session-based vs. Token-based Authentication

การทำความเข้าใจความแตกต่างระหว่าง Authentication แบบ Session-based (ที่ใช้ Cookies) กับ Token-based (ที่ใช้ JWT) เป็นสิ่งสำคัญในการตัดสินใจเลือกสถาปัตยกรรมที่เหมาะสมสำหรับแอปพลิเคชันของคุณครับ

คุณสมบัติ Session-based Authentication (Cookies) Token-based Authentication (JWT)
หลักการทำงาน เมื่อผู้ใช้ล็อกอินสำเร็จ เซิร์ฟเวอร์จะสร้าง Session ID และเก็บไว้ใน Cookie ของเบราว์เซอร์ พร้อมทั้งเก็บข้อมูล Session ไว้ในเซิร์ฟเวอร์ เมื่อผู้ใช้ล็อกอินสำเร็จ เซิร์ฟเวอร์จะสร้าง JWT และส่งกลับให้ Client (เบราว์เซอร์หรือแอปฯ) Client เก็บ JWT ไว้และส่งไปกับทุกคำขอ
Statelessness Stateful: เซิร์ฟเวอร์ต้องเก็บสถานะของ Session ผู้ใช้ (ในหน่วยความจำ, ฐานข้อมูล, Redis) Stateless: เซิร์ฟเวอร์ไม่จำเป็นต้องเก็บสถานะของ Session ผู้ใช้ ข้อมูลที่จำเป็นทั้งหมดอยู่ใน JWT
Scalability (การขยายขนาด) ท้าทายกว่าในระบบกระจาย (Distributed Systems) เพราะต้องจัดการ Session State ข้ามเซิร์ฟเวอร์ (Sticky Sessions, Shared Sessions) ง่ายต่อการขยายขนาด (Scale Horizontally) เพราะแต่ละคำขอสามารถประมวลผลโดยเซิร์ฟเวอร์ใดก็ได้โดยไม่ต้องพึ่งพา Session State
Cross-domain/CORS มักมีปัญหา Same-Origin Policy (SOP) และ CORS ในการส่ง Cookie ข้ามโดเมน ทำงานได้ดีกับ CORS เพราะ JWT สามารถส่งใน HTTP Header (Authorization: Bearer) ซึ่งไม่มีข้อจำกัดของ SOP สำหรับ Cookie
Mobile/SPA Friendliness ไม่เหมาะกับ Mobile Apps หรือ SPAs ที่ไม่ใช้ Cookies หรือต้องการเข้าถึง API แบบ Cross-domain เหมาะอย่างยิ่งกับ Mobile Apps และ SPAs ที่สื่อสารผ่าน API และไม่พึ่งพา Cookies
Revocation (การเพิกถอน) ง่ายต่อการเพิกถอน Session ทันทีโดยการลบ Session ID ออกจากเซิร์ฟเวอร์ ท้าทายกว่า ต้องใช้กลไก Blacklist หรือ Short Expiry Time ร่วมกับ Refresh Tokens
Security (ความเสี่ยงหลัก) CSRF (Cross-Site Request Forgery) และ Session Hijacking (หาก Cookie ไม่ปลอดภัย) XSS (Cross-Site Scripting) หาก JWT ถูกเก็บใน Local Storage, Token Theft, ไม่มีการ Revocation ทันที
Overhead เซิร์ฟเวอร์ต้องใช้หน่วยความจำ/พื้นที่เก็บข้อมูลสำหรับ Sessions JWT มีขนาดใหญ่กว่า Session ID เล็กน้อย อาจทำให้ Header คำขอมีขนาดใหญ่ขึ้น แต่เซิร์ฟเวอร์ไม่ต้องเก็บ State

แนวทางการปฏิบัติที่ดีที่สุด (Best Practices)

การนำ OAuth 2.0 และ JWT ไปใช้งานอย่างปลอดภัยและมีประสิทธิภาพต้องอาศัยแนวทางการปฏิบัติที่ดีที่สุดเหล่านี้ครับ

การจัดการ Token: การจัดเก็บและการส่ง

  • สำหรับ Access Token (ที่เป็น JWT):

    • HTTP-only Cookies: เป็นวิธีที่ปลอดภัยที่สุดสำหรับ Web Applications ครับ Cookie ที่เป็น HTTP-only ไม่สามารถเข้าถึงได้ด้วย JavaScript ทำให้ป้องกันการโจมตีแบบ XSS ได้ดีเยี่ยมครับ อย่างไรก็ตาม อาจมีข้อจำกัดเรื่อง CORS หาก Client และ Resource Server อยู่คนละโดเมน.
    • Memory (RAM): สำหรับ SPA/Mobile App ควรเก็บไว้ในหน่วยความจำของแอปพลิเคชัน (in-memory) และลบทิ้งเมื่อผู้ใช้ออกจากระบบ หรือเมื่อแอปพลิเคชันปิดตัวลง เพื่อลดความเสี่ยงจากการโจมตีแบบ Persistent Storage.
    • ไม่แนะนำ Local Storage/Session Storage: แม้จะสะดวก แต่มีความเสี่ยงสูงต่อการโจมตีแบบ XSS เนื่องจาก JavaScript สามารถเข้าถึงข้อมูลใน Local Storage/Session Storage ได้ง่ายครับ
  • สำหรับ Refresh Token:

    • ควรเก็บไว้ใน HTTP-only, Secure Cookie สำหรับ Web Applications ครับ หรือใน Secure Storage ของอุปกรณ์ (เช่น Keychain บน iOS, Encrypted Shared Preferences บน Android) สำหรับ Mobile Applications.
    • Refresh Token ควรมีอายุยาวนานกว่า Access Token และถูกส่งไปเพื่อขอ Access Token ใหม่เท่านั้น ไม่ควรใช้ในการเข้าถึง API โดยตรง.
  • การส่ง Access Token: ควรส่งใน HTTP Header Authorization: Bearer <token> เสมอครับ

การหมดอายุของ Token และ Refresh Token

  • Access Token ควรมีอายุสั้น: โดยทั่วไปไม่กี่นาทีถึงไม่กี่ชั่วโมง เพื่อจำกัดระยะเวลาที่โทเค็นที่ถูกขโมยจะใช้งานได้.
  • ใช้ Refresh Token: เพื่อให้ผู้ใช้ไม่ต้องล็อกอินใหม่บ่อยๆ แต่ Refresh Token ควรมีอายุยาวนานกว่าและถูกเก็บรักษาไว้อย่างปลอดภัยสูงสุดครับ.
  • Revoke Refresh Token: หากสงสัยว่า Refresh Token ถูกบุกรุก หรือผู้ใช้เปลี่ยนรหัสผ่าน ควรมีกลไกในการเพิกถอน Refresh Token ทันที.

การจัดการคีย์ลับอย่างปลอดภัย

  • Secret Key/Private Key: คีย์ที่ใช้ในการสร้างและตรวจสอบ Signature ของ JWT (และ Client Secret ใน OAuth 2.0) ต้องเป็นความลับสูงสุด ห้ามเปิดเผยสู่สาธารณะ ห้าม Hardcode ใน Source Code และควรเก็บไว้ในตัวแปรสภาพแวดล้อม หรือระบบจัดการ Secret ที่ปลอดภัยครับ.
  • Rotation: ควรมีการเปลี่ยนคีย์ลับเป็นประจำ (Key Rotation) เพื่อลดความเสี่ยงหากคีย์รั่วไหลครับ

การตรวจสอบความถูกต้องของข้อมูล (Input Validation)

  • ตรวจสอบทุกพารามิเตอร์ที่ได้รับจาก Client ไม่ว่าจะเป็น Redirect URI, Scope, Grant Type เพื่อป้องกันการโจมตีแบบ Injection หรือการใช้ค่าที่ไม่ถูกต้องครับ

ใช้ HTTPS/TLS เสมอ

  • การสื่อสารทั้งหมดที่เกี่ยวข้องกับ OAuth 2.0 และ JWT (การแลกเปลี่ยนโค้ด, การส่ง Token) ต้องอยู่ภายใต้ HTTPS/TLS เพื่อป้องกันการดักจับข้อมูล (Man-in-the-Middle attacks) ครับ

จำกัด Scope และสิทธิ์

  • Client ควรขอสิทธิ์ (Scopes) เท่าที่จำเป็นต่อการทำงานของแอปพลิเคชันเท่านั้น เพื่อลดผลกระทบหาก Client ถูกโจมตี และเพื่อเคารพความเป็นส่วนตัวของผู้ใช้ครับ

ตัวอย่างสถานการณ์การใช้งานจริง

เพื่อให้เห็นภาพชัดเจนขึ้น เรามาดูตัวอย่างการนำ OAuth 2.0 และ JWT ไปใช้งานในสถานการณ์ต่างๆ ครับ

แอปพลิเคชันเว็บ (Web Application)

สมมติว่าคุณมีเว็บไซต์อีคอมเมิร์ซ (Client) ที่ต้องการให้ผู้ใช้สามารถล็อกอินด้วยบัญชี Google (Authorization Server/Resource Server) และเข้าถึงข้อมูลโปรไฟล์บางส่วนจาก Google ได้

  1. ผู้ใช้ คลิกปุ่ม “เข้าสู่ระบบด้วย Google” บนเว็บไซต์อีคอมเมิร์ซของคุณ
  2. เว็บไซต์อีคอมเมิร์ซ จะเปลี่ยนเส้นทาง (Redirect) ผู้ใช้ไปยังหน้าล็อกอินและขออนุญาตของ Google พร้อมระบุ client_id, redirect_uri, scope (เช่น email profile) และ response_type=code (Authorization Code Grant).
  3. ผู้ใช้ ล็อกอินเข้าสู่บัญชี Google และยืนยันการอนุญาตให้เว็บไซต์อีคอมเมิร์ซเข้าถึงข้อมูลโปรไฟล์ของตน.
  4. Google จะส่ง authorization_code กลับมายัง redirect_uri ของเว็บไซต์อีคอมเมิร์ซ.
  5. เว็บไซต์อีคอมเมิร์ซ (Backend Server) จะรับ authorization_code มา และส่งคำขอ POST ไปยัง Google Token Endpoint พร้อม client_id, client_secret, authorization_code และ redirect_uri เพื่อแลกเปลี่ยนเป็น Token.
  6. Google ตรวจสอบความถูกต้องและส่ง access_token (ซึ่งเป็น JWT), refresh_token (ถ้ามี) และ id_token (ถ้าใช้ OIDC) กลับมายัง Backend Server ของเว็บไซต์อีคอมเมิร์ซ.
  7. Backend Server จะเก็บ access_token และ refresh_token ไว้ (อาจจะในฐานข้อมูลที่เข้ารหัส) และสร้าง Session ให้ผู้ใช้ หรือสร้าง JWT สำหรับ Session ภายในของตัวเอง เพื่อส่งกลับไปยังเบราว์เซอร์ของผู้ใช้ (ใน HTTP-only Cookie).
  8. เมื่อผู้ใช้เข้าถึงหน้าอื่นๆ ของเว็บไซต์ Backend Server จะใช้ JWT ภายในของตัวเอง (จาก Cookie) เพื่อยืนยันตัวตน และใช้ access_token (จาก Google) เพื่อเรียก Google API (เช่น เพื่อดึงรูปโปรไฟล์) โดยส่ง access_token ใน Header Authorization: Bearer ไปยัง Google Resource Server.

แอปพลิเคชันมือถือ (Mobile Application) หรือ Single Page Application (SPA)

สถานการณ์คล้ายกัน แต่มีความแตกต่างที่สำคัญในการจัดการ Token และ Grant Type

  1. ผู้ใช้ คลิกปุ่ม “เข้าสู่ระบบ” ในแอปพลิเคชันมือถือของคุณ.
  2. แอปพลิเคชันมือถือ จะเริ่มกระบวนการ OAuth 2.0 โดยใช้ Authorization Code Grant พร้อม PKCE โดยเปิดหน้าล็อกอินของ Identity Provider (เช่น Google, Facebook) ผ่าน Custom Tab ในเบราว์เซอร์ของระบบ.
  3. ผู้ใช้ ล็อกอินและให้สิทธิ์.
  4. Identity Provider ส่ง authorization_code กลับไปยัง redirect_uri ของแอปพลิเคชันมือถือ.
  5. แอปพลิเคชันมือถือ รับ authorization_code และส่งคำขอ POST ไปยัง Token Endpoint ของ Identity Provider พร้อม client_id, authorization_code, redirect_uri, code_verifier (จาก PKCE) เพื่อแลกเปลี่ยนเป็น Token. (ในกรณีของ Mobile/SPA ไม่มี Client Secret)
  6. Identity Provider ตรวจสอบความถูกต้องและส่ง access_token (JWT), refresh_token และ id_token (ถ้าใช้ OIDC) กลับมายังแอปพลิเคชันมือถือ.
  7. แอปพลิเคชันมือถือ เก็บ access_token ไว้ในหน่วยความจำชั่วคราว หรือ Secure Storage ของอุปกรณ์ และ refresh_token ใน Secure Storage.
  8. เมื่อแอปพลิเคชันต้องการเรียก API ของ Backend Server ของคุณ (หรือ Resource Server ภายนอก) ก็จะส่ง access_token (JWT) ใน Header Authorization: Bearer ไปพร้อมกับคำขอ.
  9. Backend Server/Resource Server ตรวจสอบ JWT เพื่อยืนยันตัวตนและสิทธิ์ และประมวลผลคำขอ.
  10. เมื่อ access_token หมดอายุ แอปพลิเคชันมือถือ จะใช้ refresh_token ที่เก็บไว้อย่างปลอดภัย เพื่อขอ access_token ใหม่จาก Identity Provider โดยอัตโนมัติ.

คำถามที่พบบ่อย (FAQ)

Q1: OAuth 2.0 กับ JWT ต่างกันอย่างไรครับ?

A1: OAuth 2.0 คือโปรโตคอลสำหรับการ อนุญาต (Authorization) ครับ มันเป็นกระบวนการที่แอปพลิเคชันหนึ่งได้รับสิทธิ์ในการเข้าถึงทรัพยากรของผู้ใช้จากอีกบริการหนึ่ง โดยไม่ต้องรู้ข้อมูลประจำตัวของผู้ใช้ครับ ส่วน JWT (JSON Web Token) คือ รูปแบบของ Token ครับ มันเป็นวิธีการเข้ารหัสข้อมูลที่ปลอดภัย เพื่อใช้ในการ ยืนยันตัวตน (Authentication) และส่งข้อมูลระหว่างสองฝ่ายครับ บ่อยครั้งที่ OAuth 2.0 จะออก Access Token ในรูปแบบของ JWT ครับ

Q2: ทำไมต้องใช้ PKCE ร่วมกับ Authorization Code Grant สำหรับ Mobile/SPA ครับ?

A2: สำหรับแอปพลิเคชันมือถือหรือ Single Page Application (SPA) ที่ทำงานในเบราว์เซอร์ ซึ่งถือว่าเป็น “Public Clients” (ไม่มี Client Secret ที่ปลอดภัย) การใช้ Authorization Code Grant เพียงอย่างเดียวมีความเสี่ยงที่ Authorization Code อาจถูกดักจับระหว่างทางโดยแอปพลิเคชันที่เป็นอันตรายครับ PKCE (Proof Key for Code Exchange) ช่วยเพิ่มความปลอดภัยโดยการเพิ่ม “Secret” ชั่วคราว (code_verifier และ code_challenge) ที่ Client สร้างขึ้นเอง ทำให้แม้ว่า Code จะถูกดักจับไปได้ แต่แฮกเกอร์ก็ไม่สามารถนำไปแลกเป็น Access Token ได้ หากไม่มี code_verifier ที่ถูกต้องครับ

Q3: ควรเก็บ JWT ไว้ที่ไหนในเบราว์เซอร์ครับ? Local Storage, Session Storage หรือ HTTP-only Cookie?

A3: คำถามนี้เป็นที่ถกเถียงกันมากครับ

  • Local Storage/Session Storage: สะดวกในการเข้าถึงด้วย JavaScript แต่เสี่ยงต่อการโจมตี XSS อย่างมาก หากมี Script ที่เป็นอันตรายรันบนหน้าเว็บ มันจะสามารถเข้าถึงและขโมย JWT ของคุณไปได้ครับ
  • HTTP-only Cookie: เป็นวิธีที่แนะนำสำหรับ Web Application ครับ Cookie ประเภทนี้ไม่สามารถเข้าถึงได้ด้วย JavaScript ทำให้ป้องกัน XSS ได้ดีเยี่ยมครับ อย่างไรก็ตาม อาจมีข้อจำกัดเรื่อง CSRF (ต้องใช้กลไกป้องกันเพิ่มเติมเช่น CSRF Token) และ CORS หาก Client และ Resource Server อยู่คนละโดเมนครับ

สำหรับแอปพลิเคชัน SPA ที่มีการสื่อสารกับ API ข้ามโดเมน การใช้ HTTP-only Cookie อาจต้องพิจารณาอย่างรอบคอบ แต่โดยรวมแล้ว หากทำได้ HTTP-only Cookie ยังคงเป็นตัวเลือกที่ปลอดภัยที่สุดสำหรับ Web Application ครับ และสำหรับ Mobile App ควรเก็บใน Secure Storage ของอุปกรณ์ครับ

Q4: JWT ช่วยให้ระบบ Scalable ได้อย่างไรครับ?

A4: JWT ช่วยให้ระบบเป็นแบบ “Stateless” ครับ นั่นหมายความว่า เซิร์ฟเวอร์ไม่จำเป็นต้องเก็บข้อมูล Session ของผู้ใช้แต่ละคนไว้ในหน่วยความจำหรือฐานข้อมูลอีกต่อไป ข้อมูลที่จำเป็นสำหรับการยืนยันตัวตนและสิทธิ์ทั้งหมดจะถูกบรรจุอยู่ในตัว JWT เองครับ เมื่อเซิร์ฟเวอร์ได้รับ JWT มันสามารถตรวจสอบและอ่านข้อมูลได้ทันทีโดยไม่ต้องไปค้นหาข้อมูล Session ที่ใด ทำให้สามารถเพิ่มจำนวนเซิร์ฟเวอร์ได้อย่างง่ายดาย (Horizontal Scaling) โดยไม่ต้องกังวลเรื่องการจัดการ Session State ที่ซับซ้อนครับ

Q5: JWT สามารถเพิกถอน (Revoke) ได้ทันทีเหมือน Session ไหมครับ?

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

  • Blacklist/Denylist: เซิร์ฟเวอร์เก็บรายการของ JWT ที่ถูกเพิกถอนไว้ในฐานข้อมูลหรือ Cache (เช่น Redis) และตรวจสอบทุกคำขอว่า Token นั้นอยู่ใน Blacklist หรือไม่ แต่วิธีนี้จะทำให้ระบบกลับมาเป็น Stateful บางส่วนครับ
  • Short Expiry Time: กำหนดให้ Access Token มีอายุสั้นมากๆ (เช่น 5-10 นาที) และใช้ Refresh Token ที่มีอายุยาวนานกว่า แต่เก็บไว้อย่างปลอดภัย เพื่อขอ Access Token ใหม่ เมื่อ Access Token สั้นๆ หมดอายุ หาก Refresh Token ถูกเพิกถอน ก็จะไม่มี Access Token ใหม่ถูกออกครับ

Q6: ควรใส่ข้อมูลอะไรลงใน JWT Payload บ้างครับ?

A6: ควรใส่ข้อมูลที่จำเป็นสำหรับการยืนยันตัวตนและตัดสินใจเรื่องสิทธิ์ (Authorization) เท่านั้นครับ เช่น User ID, Username, Roles/Permissions, หรือ Scopes ที่ผู้ใช้ได้รับอนุญาตครับ ไม่ควรใส่ข้อมูลที่อ่อนไหวมากๆ (เช่น รหัสผ่าน, ข้อมูลบัตรเครดิต) หรือข้อมูลที่มีขนาดใหญ่เกินไป เพราะข้อมูลใน Payload ไม่ได้ถูกเข้ารหัสเป็นความลับ (Confidentiality) แต่เป็นเพียงการเข้ารหัส Base64 ซึ่งสามารถถอดรหัสออกมาอ่านได้ง่ายครับ และหาก Payload มีขนาดใหญ่เกินไป จะทำให้ขนาดของ Token และ HTTP Request Header ใหญ่ขึ้นโดยไม่จำเป็นครับ

สรุปและ Call-to-Action

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

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

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

จัดส่งรวดเร็วส่งด่วนทั่วประเทศ
รับประกันสินค้าเคลมง่าย มีใบรับประกัน
ผ่อนชำระได้บัตรเครดิต 0% สูงสุด 10 เดือน
สะสมแต้ม รับส่วนลดส่วนลดและคะแนนสะสม

© 2026 SiamLancard — จำหน่ายการ์ดแลน อุปกรณ์ Server และเครื่องพิมพ์ใบเสร็จ

SiamLancard
Logo
Free Forex EA Download — XM Signal · EA Forex ฟรี
iCafeForex.com - สอนเทรด Forex | SiamCafe.net
Shopping cart