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

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

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

สารบัญ

ทำไมต้องเข้าใจ OAuth 2.0 และ JWT?

ก่อนที่เราจะดำดิ่งลงไปในรายละเอียด ลองนึกภาพโลกดิจิทัลในปัจจุบันดูนะครับ เรามีแอปพลิเคชันมากมายที่ต้องการเข้าถึงข้อมูลหรือบริการจากที่อื่น เช่น คุณอาจต้องการให้แอปพลิเคชันแต่งรูปเข้าถึงรูปภาพของคุณบน Google Photos หรือให้แอปพลิเคชันจองตั๋วเครื่องบินเข้าถึงข้อมูลโปรไฟล์ของคุณบน Facebook เพื่อความสะดวกสบายในการกรอกข้อมูล

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

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

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

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

เจาะลึก OAuth 2.0: การอนุญาตสิทธิ์ที่ปลอดภัย

OAuth 2.0 คืออะไร?

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

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

บทบาทหลักใน OAuth 2.0

เพื่อให้เข้าใจภาพรวมของ OAuth 2.0 ได้ง่ายขึ้น มาดูบทบาทหลักๆ ที่เกี่ยวข้องในการทำงานของมันกันครับ

  • Resource Owner: คือตัวผู้ใช้งานเองครับ เป็นบุคคลที่มีข้อมูลหรือทรัพยากรที่ต้องการป้องกัน (เช่น รูปภาพบน Google Photos, ข้อมูลโปรไฟล์บน Facebook) และเป็นผู้ที่ตัดสินใจว่าจะอนุญาตให้แอปพลิเคชันอื่นเข้าถึงทรัพยากรเหล่านั้นได้หรือไม่
  • Client (Application): คือแอปพลิเคชันที่ต้องการเข้าถึงทรัพยากรของ Resource Owner (เช่น แอปแต่งรูป, แอปจองตั๋ว) Client จะต้องลงทะเบียนกับ Authorization Server ก่อน จึงจะได้รับ Client ID และ Client Secret
  • Authorization Server: เป็นเซิร์ฟเวอร์ที่ทำหน้าที่ยืนยันตัวตนของ Resource Owner และออก Access Token ให้กับ Client หลังจากที่ Resource Owner ได้ให้การอนุญาตแล้วครับ
  • Resource Server: เป็นเซิร์ฟเวอร์ที่จัดเก็บ Protected Resources ของ Resource Owner และสามารถเข้าถึงได้ด้วย Access Token ที่ถูกต้องเท่านั้นครับ

ลองจินตนาการถึงสถานการณ์ที่คุณไปธนาคาร (Authorization Server) เพื่อขอให้ธนาคารออกบัตรเครดิต (Access Token) ให้กับคุณ เพื่อที่คุณจะสามารถใช้บัตรนั้นไปซื้อของที่ร้านค้า (Resource Server) ได้ โดยที่คุณไม่ต้องให้เงินสด (Username/Password) กับร้านค้าโดยตรงครับ

ประเภทของ Grant Types (Authorization Flow)

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

Authorization Code Grant (สำหรับ Web Application)

นี่คือ Grant Type ที่ได้รับความนิยมและปลอดภัยที่สุดสำหรับแอปพลิเคชันบนเว็บที่มี Backend และสามารถเก็บ Client Secret ได้อย่างปลอดภัยครับ

  1. Client ขอสิทธิ์: Resource Owner เข้าสู่ระบบ Client (แอปพลิเคชัน) Client จะพา Resource Owner ไปยัง Authorization Server พร้อมกับ client_id, redirect_uri, และ scope ที่ต้องการ
  2. Resource Owner อนุญาต: Authorization Server ยืนยันตัวตนของ Resource Owner (เช่น ให้ล็อกอิน) และขอการอนุญาตให้ Client เข้าถึงข้อมูลตาม scope ที่ร้องขอ หาก Resource Owner อนุญาต Authorization Server จะส่ง authorization_code กลับไปยัง redirect_uri ของ Client
  3. Client แลกเปลี่ยน Code เป็น Token: Client ได้รับ authorization_code และส่ง Code นี้ พร้อมกับ client_id, client_secret, และ redirect_uri กลับไปที่ Authorization Server ผ่านช่องทางที่ปลอดภัย (เช่น POST request จาก Backend)
  4. Authorization Server ออก Token: Authorization Server ตรวจสอบข้อมูลทั้งหมด ถ้าถูกต้อง จะออก access_token และอาจจะมี refresh_token (รวมถึง id_token หากใช้ OIDC) ให้กับ Client
  5. Client ใช้ Access Token: Client ใช้ access_token ที่ได้รับมา เพื่อร้องขอข้อมูลจาก Resource Server ในนามของ Resource Owner ครับ

ข้อดี: มีความปลอดภัยสูง เนื่องจาก access_token ไม่ได้ถูกส่งผ่าน URL และ client_secret ถูกเก็บไว้อย่างปลอดภัยที่ฝั่ง Backend ของ Client

ในปัจจุบัน เพื่อเพิ่มความปลอดภัยสำหรับ Public Clients (เช่น Mobile/SPA applications) ที่ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัย Authorization Code Grant มักจะใช้ร่วมกับ PKCE (Proof Key for Code Exchange) ครับ อ่านเพิ่มเติมเกี่ยวกับ PKCE

Client Credentials Grant (สำหรับ Machine-to-Machine)

Grant Type นี้ใช้เมื่อ Client (ซึ่งอาจจะเป็น Server-side application หรือ Service) ต้องการเข้าถึง Protected Resources ของตัวเอง หรือเข้าถึง Protected Resources ที่ไม่ได้เกี่ยวข้องกับผู้ใช้โดยตรงครับ

  1. Client ร้องขอ Token: Client ส่ง client_id และ client_secret ไปยัง Authorization Server โดยตรง
  2. Authorization Server ออก Token: Authorization Server ตรวจสอบ client_id และ client_secret หากถูกต้อง จะออก access_token ให้กับ Client
  3. Client ใช้ Access Token: Client ใช้ access_token เพื่อเข้าถึง Resource Server

ข้อดี: เหมาะสำหรับระบบที่ไม่มีผู้ใช้ปลายทางเข้ามาเกี่ยวข้อง เช่น Microservices สื่อสารกันเอง

Implicit Grant (Deprecated)

เป็น Grant Type ที่เคยนิยมใช้สำหรับ Single Page Applications (SPAs) หรือ Mobile Applications ที่ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัยครับ

วิธีการ: Resource Owner อนุญาตสิทธิ์แล้ว Authorization Server จะส่ง access_token กลับไปยัง redirect_uri ของ Client โดยตรงผ่าน URL fragment

ข้อเสีย: ไม่ปลอดภัยเนื่องจาก access_token ถูกส่งผ่าน URL fragment ซึ่งอาจถูกดักจับได้ง่าย และไม่มี refresh_token ทำให้ต้องขอ access_token ใหม่บ่อยๆ

ปัจจุบัน: ไม่แนะนำให้ใช้แล้วครับ ควรหันไปใช้ Authorization Code Grant with PKCE แทน

Resource Owner Password Credentials Grant (Deprecated)

Grant Type นี้ให้ Client สามารถขอ Username และ Password ของ Resource Owner โดยตรง และส่งไปยัง Authorization Server เพื่อแลกเป็น Access Token ครับ

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

ปัจจุบัน: ไม่แนะนำให้ใช้แล้วครับ ควรใช้ในกรณีที่ Client เป็นแอปพลิเคชันที่เชื่อถือได้มากๆ (เช่น แอปพลิเคชันของบริษัทเอง) และไม่สามารถใช้ Grant Type อื่นได้จริงๆ เท่านั้นครับ

Refresh Token

refresh_token เป็นโทเค็นระยะยาวที่ Authorization Server ออกให้พร้อมกับ access_token ครับ มีหน้าที่ในการขอ access_token ใหม่เมื่อ access_token ตัวเก่าหมดอายุ โดยที่ Resource Owner ไม่ต้องล็อกอินใหม่หรือให้การอนุญาตซ้ำอีกครั้ง

ความสำคัญ: ช่วยให้ access_token มีอายุสั้นลงได้ เพื่อลดความเสี่ยงหาก Access Token ถูกขโมยไป และยังคงรักษาประสบการณ์ผู้ใช้ที่ดีอยู่ครับ

ข้อควรระวัง: refresh_token มีอายุยาวนานกว่า จึงต้องเก็บรักษาไว้อย่างปลอดภัยที่สุดครับ

องค์ประกอบสำคัญของ OAuth 2.0

  • Client ID: ตัวระบุที่ไม่ซ้ำกันสำหรับ Client ที่ลงทะเบียนกับ Authorization Server
  • Client Secret: รหัสลับที่ใช้ในการยืนยันตัวตนของ Client กับ Authorization Server (ควรเก็บเป็นความลับและปลอดภัยที่สุด)
  • Redirect URI: URL ที่ Authorization Server จะส่งผู้ใช้กลับมาหลังจากที่ผู้ใช้ได้ให้การอนุญาตแล้ว ต้องเป็น URI ที่ลงทะเบียนไว้ล่วงหน้าเท่านั้น
  • Scope: ขอบเขตของการอนุญาตที่ Client ต้องการจาก Resource Owner (เช่น “read_profile”, “write_photos”)
  • Access Token: โทเค็นที่ Client ใช้เพื่อเข้าถึง Protected Resources บน Resource Server เป็นโทเค็นที่มีอายุสั้น
  • Refresh Token: โทเค็นระยะยาวที่ใช้เพื่อขอ Access Token ใหม่ เมื่อ Access Token เดิมหมดอายุ

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

แม้ OAuth 2.0 จะช่วยเพิ่มความปลอดภัย แต่ก็มีจุดที่ต้องระวังเพื่อป้องกันการโจมตีต่างๆ ครับ

  • HTTPS Everywhere: การสื่อสารทั้งหมดระหว่าง Client, Authorization Server, และ Resource Server ต้องทำผ่าน HTTPS เท่านั้น เพื่อป้องกันการดักจับข้อมูล (Man-in-the-Middle attacks)
  • Validate Redirect URIs: ตรวจสอบให้แน่ใจว่า redirect_uri ที่ส่งมาตรงกับที่ลงทะเบียนไว้กับ Authorization Server เสมอ เพื่อป้องกันการ Redirect ไปยังเว็บไซต์ที่เป็นอันตราย
  • Secure Client Secret: Client Secret ต้องถูกเก็บไว้อย่างปลอดภัยที่ฝั่ง Server-side ของ Client เท่านั้น ห้ามเปิดเผยใน Code ที่รันฝั่ง Client (เช่น JavaScript ใน SPA หรือ Mobile App)
  • PKCE (Proof Key for Code Exchange): สำหรับ Public Clients (เช่น Mobile App, SPA) ที่ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัย ควรใช้ PKCE ร่วมกับ Authorization Code Grant เพื่อป้องกัน Authorization Code Interception Attack
  • CSRF Protection: ใช้พารามิเตอร์ state ใน Authorization Request เพื่อป้องกัน Cross-Site Request Forgery (CSRF) โดย Authorization Server จะส่งค่า state นี้กลับมา และ Client ต้องตรวจสอบว่าตรงกับค่าที่ส่งไป
  • Limit Scopes: ขอ Scope เท่าที่จำเป็นจริงๆ เท่านั้น เพื่อจำกัดขอบเขตความเสียหายหาก Access Token ถูกขโมยไป
  • Token Revocation: ควรมีกลไกในการ Revoke (ยกเลิก) Access Token และ Refresh Token ในกรณีที่ถูกขโมยหรือผู้ใช้ต้องการยกเลิกสิทธิ์

การนำ OAuth 2.0 ไปใช้งานอย่างถูกต้องและปลอดภัยนั้น ต้องอาศัยความเข้าใจในกลไกและข้อควรระวังต่างๆ เป็นอย่างดีครับ

เจาะลึก JWT (JSON Web Tokens): โทเค็นที่ยืนยันตัวตนได้ด้วยตัวเอง

JWT คืออะไร?

JWT ย่อมาจาก “JSON Web Token” เป็นมาตรฐาน (RFC 7519) ที่ใช้วิธีที่กะทัดรัด (Compact) และปลอดภัย (URL-safe) ในการแสดงข้อมูลระหว่างสองฝ่ายในรูปแบบของ JSON Object ครับ ข้อมูลนี้สามารถตรวจสอบความถูกต้องได้ เนื่องจากมีการลงชื่อ (Signed) ด้วย Digital Signature

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

JWT มักถูกนำมาใช้ในสถานการณ์ต่อไปนี้:

  • Authorization: หลังจากผู้ใช้ล็อกอินสำเร็จ Server จะออก JWT ให้ Client Client จะใช้ JWT นี้ส่งไปกับทุก Request เพื่อยืนยันว่าผู้ใช้คนนี้ได้รับอนุญาตให้เข้าถึงทรัพยากรนั้นๆ
  • Information Exchange: การแลกเปลี่ยนข้อมูลที่ปลอดภัยระหว่างสองฝ่าย เนื่องจาก JWT สามารถลงชื่อด้วย Digital Signature ทำให้มั่นใจได้ว่าผู้ส่งเป็นผู้ที่อ้างสิทธิ์จริง และข้อมูลไม่ถูกเปลี่ยนแปลง

โครงสร้างของ JWT

JWT ประกอบด้วยสามส่วนหลักๆ ที่คั่นด้วยจุด (.) ครับ คือ Header, Payload, และ Signature

header.payload.signature

Header

ส่วน Header มักประกอบด้วยข้อมูลสองส่วนหลักๆ คือ:

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

ตัวอย่าง Header ที่ถูกเข้ารหัส Base64Url:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload (Claims)

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

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

ตัวอย่าง Payload ที่ถูกเข้ารหัส Base64Url:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1516239022,
  "exp": 1516242622
}

Signature

ส่วน Signature ใช้สำหรับตรวจสอบว่า JWT ไม่ได้ถูกเปลี่ยนแปลงระหว่างทาง และถูกสร้างโดยผู้ที่รู้ Secret Key เท่านั้นครับ

วิธีการสร้าง Signature คือ:

  1. นำ Header และ Payload ที่ถูกเข้ารหัส Base64Url มาต่อกันด้วยจุด (.)
  2. นำผลลัพธ์ที่ได้ไปเข้ารหัสด้วยอัลกอริทึมที่ระบุใน Header (เช่น HS256) พร้อมกับ Secret Key ที่ Server ใช้ในการลงชื่อ

ตัวอย่างการสร้าง Signature ด้วย HS256:

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

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

ประเภทของ JWT: JWS และ JWE

โดยทั่วไป JWT ที่เราพูดถึงกันคือ JWS (JSON Web Signature) ซึ่งเป็น JWT ที่มีการลงชื่อ (Signed) เพื่อรับประกันความสมบูรณ์ของข้อมูล แต่ไม่ได้เข้ารหัสข้อมูลภายใน Payload ครับ ดังนั้นข้อมูลใน Payload จึงสามารถอ่านได้ (แต่ไม่สามารถแก้ไขได้โดยไม่ทำให้ Signature เสีย)

นอกจากนี้ยังมี JWE (JSON Web Encryption) ซึ่งเป็น JWT ที่มีการเข้ารหัส (Encrypted) ข้อมูลภายใน Payload ด้วย เพื่อปกป้องความเป็นส่วนตัวของข้อมูลครับ JWE มักจะถูกใช้ในกรณีที่ต้องการส่งข้อมูลที่ละเอียดอ่อนมากๆ ครับ

ในบริบทของการ Authentication และ Authorization ส่วนใหญ่จะใช้ JWS ครับ

ข้อดีของการใช้ JWT

  • Stateless: Server ไม่จำเป็นต้องเก็บ Session State ทำให้ scalability ดีขึ้นมาก เหมาะสำหรับ Microservices และ Distributed Systems
  • Compact: มีขนาดเล็ก สามารถส่งผ่าน URL, POST parameter หรือ HTTP header ได้ง่ายและรวดเร็ว
  • Self-contained: มีข้อมูลที่จำเป็นสำหรับการยืนยันตัวตนและการอนุญาตสิทธิ์อยู่ในตัวโทเค็นเอง Server จึงไม่จำเป็นต้อง query database บ่อยๆ
  • URL-safe: สามารถส่งผ่าน URL ได้อย่างปลอดภัย

ข้อควรพิจารณาด้านความปลอดภัยสำหรับ JWT

แม้ JWT จะมีข้อดีมากมาย แต่ก็มีข้อควรระวังด้านความปลอดภัยที่ต้องให้ความสำคัญครับ

  • Secret Key Management: Secret Key ที่ใช้ในการลงชื่อ JWT ต้องเป็นความลับสุดยอด และมีความยาวเพียงพอ (อย่างน้อย 256 บิตสำหรับ HS256) หาก Secret Key รั่วไหล ผู้โจมตีสามารถสร้าง JWT ปลอมได้
  • Expiration Time (exp claim): กำหนด exp claim ให้มีอายุสั้นที่สุดเท่าที่จะเป็นไปได้ (เช่น 5-15 นาที) เพื่อลดความเสี่ยงหาก Access Token ถูกขโมยไป
  • Audience Validation (aud claim): ตรวจสอบ aud claim เพื่อให้แน่ใจว่าโทเค็นถูกสร้างมาสำหรับ Client หรือ Resource Server ของคุณเท่านั้น
  • Issuer Validation (iss claim): ตรวจสอบ iss claim เพื่อให้แน่ใจว่าโทเค็นมาจากผู้ออกที่เชื่อถือได้เท่านั้น
  • Don’t Store Sensitive Data in Payload: เนื่องจาก Payload ของ JWT ไม่ได้เข้ารหัส (ใน JWS) ข้อมูลที่เก็บในนั้นจึงไม่ควรเป็นข้อมูลที่ละเอียดอ่อนมากๆ ครับ
  • Algorithm Confusion Attacks: ตรวจสอบให้แน่ใจว่า Server ของคุณไม่ได้อนุญาตให้ Client ระบุ alg ใน Header เป็น “none” หรือใช้ Key สาธารณะในการตรวจสอบโทเค็นที่ถูกสร้างด้วย Key ส่วนตัว
  • Token Revocation: JWT โดยธรรมชาติเป็น Stateless ซึ่งหมายความว่าเมื่อออกไปแล้ว การยกเลิก (Revoke) จะทำได้ยาก หากต้องการกลไก Revocation ต้องมีการสร้าง Blacklist หรือ Whitelist ที่ฝั่ง Server เพื่อตรวจสอบทุกครั้งที่ได้รับ JWT ซึ่งจะทำให้เสียคุณสมบัติ Stateless ไปบางส่วนครับ
  • Cross-Site Scripting (XSS): หากเก็บ JWT ใน Local Storage ของ Browser อาจถูกโจมตีด้วย XSS ได้ ควรเก็บไว้ใน HttpOnly cookies หรือในหน่วยความจำของแอปพลิเคชัน (สำหรับ SPA/Mobile) เพื่อลดความเสี่ยง

ตัวอย่าง Code Snippet: การสร้างและตรวจสอบ JWT

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

# pip install PyJWT
import jwt
import datetime
import time

# --- การตั้งค่า Secret Key ---
# Secret Key ควรเป็นสตริงที่ยาวและซับซ้อน และเก็บไว้ใน Environment Variable
# ห้าม Hardcode ในโค้ดจริง!
SECRET_KEY = "your-very-secret-and-long-key-that-no-one-can-guess-1234567890"

# --- 1. การสร้าง JWT ---
def create_jwt_token(user_id, is_admin=False):
    # กำหนดเวลาหมดอายุของโทเค็น (เช่น 1 ชั่วโมง)
    expiration_time = datetime.datetime.utcnow() + datetime.timedelta(hours=1)
    
    # Payload หรือ Claims ที่จะใส่ใน JWT
    payload = {
        "user_id": user_id,
        "is_admin": is_admin,
        "exp": expiration_time,  # เวลาหมดอายุ
        "iat": datetime.datetime.utcnow(), # เวลาที่ออกโทเค็น
        "iss": "siamlancard.com", # ผู้ออกโทเค็น
        "aud": "my_api_service" # ผู้รับโทเค็น
    }

    # สร้าง JWT โดยใช้ HS256 algorithm
    token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
    return token

# --- 2. การตรวจสอบ JWT ---
def verify_jwt_token(token):
    try:
        # ตรวจสอบโทเค็นโดยใช้ Secret Key และอัลกอริทึม
        # รวมถึงตรวจสอบ 'exp', 'iat', 'iss', 'aud' claims โดยอัตโนมัติ
        decoded_payload = jwt.decode(
            token, 
            SECRET_KEY, 
            algorithms=["HS256"],
            issuer="siamlancard.com",
            audience="my_api_service"
        )
        return decoded_payload
    except jwt.ExpiredSignatureError:
        print("Token has expired.")
        return None
    except jwt.InvalidTokenError as e:
        print(f"Invalid token: {e}")
        return None

# --- ตัวอย่างการใช้งาน ---
if __name__ == "__main__":
    print("--- สร้าง JWT สำหรับผู้ใช้ปกติ ---")
    user_token = create_jwt_token("user123", is_admin=False)
    print(f"Generated User Token: {user_token}")

    print("\n--- ตรวจสอบ JWT สำหรับผู้ใช้ปกติ ---")
    decoded_user_payload = verify_jwt_token(user_token)
    if decoded_user_payload:
        print(f"Decoded User Payload: {decoded_user_payload}")
        print(f"User ID: {decoded_user_payload.get('user_id')}")
        print(f"Is Admin: {decoded_user_payload.get('is_admin')}")

    print("\n--- สร้าง JWT สำหรับผู้ดูแลระบบ ---")
    admin_token = create_jwt_token("admin456", is_admin=True)
    print(f"Generated Admin Token: {admin_token}")

    print("\n--- ตรวจสอบ JWT สำหรับผู้ดูแลระบบ ---")
    decoded_admin_payload = verify_jwt_token(admin_token)
    if decoded_admin_payload:
        print(f"Decoded Admin Payload: {decoded_admin_payload}")
        print(f"User ID: {decoded_admin_payload.get('user_id')}")
        print(f"Is Admin: {decoded_admin_payload.get('is_admin')}")

    print("\n--- ทดสอบโทเค็นหมดอายุ (จำลอง) ---")
    # สร้างโทเค็นที่หมดอายุทันทีเพื่อทดสอบ
    payload_expired = {
        "user_id": "expired_user",
        "exp": datetime.datetime.utcnow() - datetime.timedelta(seconds=1), # หมดอายุไปแล้ว
        "iat": datetime.datetime.utcnow(),
        "iss": "siamlancard.com",
        "aud": "my_api_service"
    }
    expired_token = jwt.encode(payload_expired, SECRET_KEY, algorithm="HS256")
    print(f"Generated Expired Token: {expired_token}")

    print("\n--- ตรวจสอบโทเค็นหมดอายุ ---")
    decoded_expired_payload = verify_jwt_token(expired_token)
    if not decoded_expired_payload:
        print("Correctly identified expired token.")

    print("\n--- ทดสอบโทเค็นที่ไม่ถูกต้อง (แก้ไข Payload) ---")
    # ลองแก้ไขส่วน Payload ของโทเค็นที่ถูกต้อง
    parts = user_token.split('.')
    modified_payload_base64 = jwt.base64url_encode(
        '{"user_id": "hacker", "is_admin": true, "exp": 2000000000, "iat": 1516239022, "iss": "siamlancard.com", "aud": "my_api_service"}'.encode('utf-8')
    ).decode('utf-8')
    malicious_token = f"{parts[0]}.{modified_payload_base64}.{parts[2]}"
    print(f"Generated Malicious Token: {malicious_token}")
    
    print("\n--- ตรวจสอบโทเค็นที่ไม่ถูกต้อง ---")
    decoded_malicious_payload = verify_jwt_token(malicious_token)
    if not decoded_malicious_payload:
        print("Correctly identified malicious token (signature mismatch).")

จากตัวอย่างโค้ดนี้ จะเห็นว่า jwt.encode() ใช้ในการสร้าง JWT โดยมี Payload และ Secret Key เป็นส่วนสำคัญ ส่วน jwt.decode() ใช้ในการตรวจสอบ JWT ซึ่งจะทำการตรวจสอบ Signature, เวลาหมดอายุ (exp), ผู้ออก (iss), และผู้รับ (aud) โดยอัตโนมัติ ทำให้เรามั่นใจได้ว่าโทเค็นนั้นถูกต้องและยังไม่หมดอายุครับ

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

OAuth 2.0 + JWT: คู่หูที่ลงตัว

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

เมื่อนำทั้งสองมารวมกัน OAuth 2.0 จะทำหน้าที่เป็นเฟรมเวิร์กในการจัดการขั้นตอนการขอและออกโทเค็น ส่วนโทเค็นที่ Authorization Server ออกให้ (โดยเฉพาะ Access Token และ ID Token ใน OpenID Connect) ก็มักจะอยู่ในรูปแบบของ JWT ครับ

ดังนั้น โดยสรุปคือ:

  • OAuth 2.0: จัดการ “กระบวนการ” ในการให้สิทธิ์การเข้าถึงทรัพยากร
  • JWT: คือ “รูปแบบ” ของโทเค็นที่ถูกสร้างขึ้นและส่งผ่านในกระบวนการ OAuth 2.0 เพื่อใช้ในการยืนยันตัวตนและ/หรืออนุญาตสิทธิ์

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

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

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

กล่าวคือ OIDC ใช้ OAuth 2.0 เพื่อ:

  • ยืนยันตัวตนของ Resource Owner (ผู้ใช้)
  • ให้ข้อมูลพื้นฐานเกี่ยวกับ Resource Owner แก่ Client (ผ่าน ID Token)

ดังนั้น เมื่อคุณเห็นระบบที่ใช้ “Sign in with Google” หรือ “Login with Facebook” นั่นคือตัวอย่างของการใช้ OpenID Connect (ซึ่งสร้างอยู่บน OAuth 2.0) ครับ

ลำดับการทำงานของ OIDC ที่ใช้ JWT

มาดูลำดับการทำงานโดยละเอียดเมื่อ OAuth 2.0 (โดยใช้ Authorization Code Grant) ทำงานร่วมกับ JWT ในบริบทของ OpenID Connect ครับ

  1. Client (แอปพลิเคชัน) เริ่มต้น Flow:
    • ผู้ใช้คลิก “Login with Google” บน Client App
    • Client App Redirect ผู้ใช้ไปยัง Authorization Endpoint ของ Google (Authorization Server) พร้อมกับ client_id, redirect_uri, scope (เช่น openid profile email), response_type=code, และ state (สำหรับป้องกัน CSRF)
    • ถ้าเป็น Public Client (SPA/Mobile) จะมี code_challenge และ code_challenge_method สำหรับ PKCE ด้วยครับ
  2. ผู้ใช้ยืนยันตัวตนและให้การอนุญาต:
    • ผู้ใช้ล็อกอินเข้าสู่ Google (ถ้ายังไม่ได้ล็อกอิน)
    • Google จะแสดงหน้าจอขอการอนุญาตให้ Client App เข้าถึงข้อมูลโปรไฟล์และอีเมลของผู้ใช้
    • หากผู้ใช้อนุญาต Google จะ Redirect ผู้ใช้กลับไปยัง redirect_uri ของ Client App พร้อมกับ authorization_code และ state
  3. Client App แลกเปลี่ยน Code เป็น Tokens:
    • Client App (จากฝั่ง Server-side) ส่ง authorization_code, client_id, client_secret, redirect_uri (และ code_verifier หากใช้ PKCE) ไปยัง Token Endpoint ของ Google
    • การสื่อสารนี้ทำผ่าน POST request ที่ปลอดภัย (HTTPS)
  4. Authorization Server (Google) ออก Tokens:
    • Google ตรวจสอบข้อมูลทั้งหมด
    • หากถูกต้อง Google จะตอบกลับด้วย JSON Object ที่ประกอบด้วย:
      • access_token (มักจะเป็น JWT ที่มีอายุสั้น)
      • refresh_token (มีอายุยาวนานกว่า)
      • id_token (เป็น JWT ที่มีข้อมูลยืนยันตัวตนของผู้ใช้)
      • expires_in (ระยะเวลาหมดอายุของ Access Token)
  5. Client App ใช้ ID Token และ Access Token:
    • Client App ตรวจสอบ id_token (ซึ่งเป็น JWT) เพื่อยืนยันตัวตนของผู้ใช้ เช่น ตรวจสอบ Signature, exp, iss, aud และดึงข้อมูลโปรไฟล์ผู้ใช้จาก Payload
    • Client App ใช้ access_token (ซึ่งเป็น JWT) เพื่อส่งไปกับทุกๆ API Request ที่จะเข้าถึง Protected Resources บน Resource Server (เช่น Google Photos API)
  6. Resource Server ตรวจสอบ Access Token:
    • เมื่อ Resource Server ได้รับ Request พร้อม access_token มันจะตรวจสอบความถูกต้องของ Access Token นั้น (เช่น ตรวจสอบ Signature, exp, scope)
    • หาก Access Token ถูกต้อง Resource Server จะให้สิทธิ์การเข้าถึงทรัพยากรตามที่ร้องขอ

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

ข้อดีและข้อเสียของการใช้ OAuth 2.0 และ JWT

ข้อดี

  • ความปลอดภัยสูง: OAuth 2.0 ช่วยให้แอปพลิเคชันเข้าถึงทรัพยากรโดยไม่ต้องรู้ Credentials ของผู้ใช้ ลดความเสี่ยงในการถูกขโมยข้อมูล ส่วน JWT มี Signature ที่ช่วยยืนยันความสมบูรณ์ของข้อมูล
  • Delegated Authorization: ผู้ใช้สามารถควบคุมได้ว่าจะให้แอปพลิเคชันใดเข้าถึงข้อมูลส่วนใดได้บ้าง
  • Statelessness (สำหรับ JWT): ลดภาระของ Server ในการจัดการ Session ทำให้ระบบมีความ Scalability สูงขึ้น เหมาะสำหรับ Microservices และ Distributed Systems
  • Interoperability: ทั้ง OAuth 2.0 และ JWT เป็นมาตรฐานเปิด ทำให้สามารถทำงานร่วมกับระบบและบริการต่างๆ ได้อย่างกว้างขวาง
  • Flexibility: OAuth 2.0 มี Grant Types หลายรูปแบบให้เลือกใช้ตามความเหมาะสมของ Client Type ส่วน JWT สามารถปรับแต่ง Claims ได้ตามต้องการ
  • Improved User Experience: ผู้ใช้ไม่จำเป็นต้องล็อกอินใหม่บ่อยๆ หรือเปิดเผย Username/Password ให้กับแอปพลิเคชันภายนอก

ข้อเสีย

  • ความซับซ้อนในการตั้งค่า: การทำความเข้าใจและตั้งค่า OAuth 2.0 โดยเฉพาะ Grant Type ต่างๆ อาจมีความซับซ้อนและต้องใช้ความระมัดระวัง
  • ไม่มีกลไก Revocation ในตัว (สำหรับ JWT): การยกเลิก JWT ที่ออกไปแล้วทำได้ยาก หากไม่มีกลไกเพิ่มเติม (เช่น Blacklist) อาจเป็นความเสี่ยงหาก Access Token ถูกขโมย
  • ขนาดของ JWT: หากใส่ Claims มากเกินไป JWT อาจมีขนาดใหญ่ขึ้น ทำให้ HTTP Request มีขนาดใหญ่ขึ้นด้วย
  • ความเสี่ยงจากการรั่วไหลของ Secret Key: หาก Secret Key ที่ใช้ในการลงชื่อ JWT รั่วไหล ผู้โจมตีสามารถสร้าง JWT ปลอมขึ้นมาได้
  • ไม่ใช่ Authentication Protocol โดยตรง (สำหรับ OAuth 2.0): OAuth 2.0 ไม่ได้ถูกออกแบบมาเพื่อ Authentication โดยตรง ต้องใช้ OpenID Connect เข้ามาช่วย
  • ความเสี่ยงในการจัดเก็บ Token: การจัดเก็บ Access Token และ Refresh Token ที่ไม่เหมาะสม (เช่น ใน Local Storage ของ Browser) อาจนำไปสู่การโจมตีประเภท XSS ได้

Best Practices ในการใช้งาน OAuth 2.0 และ JWT

เพื่อให้ระบบของคุณปลอดภัยและมีประสิทธิภาพสูงสุด การปฏิบัติตามแนวทางที่ดีที่สุดเป็นสิ่งสำคัญครับ

สำหรับ OAuth 2.0

  • ใช้ HTTPS เสมอ: ทุกการสื่อสารต้องอยู่ภายใต้ HTTPS เพื่อป้องกันการดักจับข้อมูล
  • Validate Redirect URIs อย่างเข้มงวด: ตรวจสอบให้แน่ใจว่า Redirect URI ที่ส่งมาตรงกับที่ลงทะเบียนไว้ทุกประการ และอนุญาตเฉพาะ URI ที่จำเป็นเท่านั้นครับ
  • ใช้ Authorization Code Grant with PKCE สำหรับ Public Clients: สำหรับ Mobile Apps และ SPAs ควรใช้ Grant Type นี้เพื่อเพิ่มความปลอดภัย เนื่องจาก Public Clients ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัย
  • เก็บ Client Secret ให้ปลอดภัย: หากเป็น Confidential Client (เช่น Web Application ที่มี Backend) Client Secret ต้องถูกเก็บไว้ใน Environment Variable หรือ Key Vault ไม่ควร Hardcode ในโค้ด และไม่ควรอยู่ใน Repository สาธารณะครับ
  • ใช้พารามิเตอร์ state เพื่อป้องกัน CSRF: สร้างค่า state ที่คาดเดาไม่ได้และเก็บไว้ใน Session ของ Client ก่อนส่ง Authorization Request และตรวจสอบ state ที่ได้รับกลับมาให้ตรงกัน
  • จำกัด Scope ให้แคบที่สุด: ขอสิทธิ์เข้าถึงข้อมูลเท่าที่จำเป็นจริงๆ เท่านั้น
  • มีกลไก Revoke Token: อนุญาตให้ผู้ใช้สามารถ Revoke Access Token หรือ Refresh Token ได้ (เช่น ในหน้า “Connected Apps”) และ Server ควรมี Endpoint สำหรับการ Revoke Token

สำหรับ JWT

  • ใช้ Secret Key/Private Key ที่แข็งแกร่งและปลอดภัย: ควรมีขนาดอย่างน้อย 256 บิตสำหรับ Symmetric Key (HS256) และเก็บเป็นความลับอย่างเข้มงวด สำหรับ Asymmetric Key (RS256) ต้องดูแล Private Key อย่างดี
  • กำหนด exp (Expiration Time) ให้สั้นที่สุด: Access Token ควรมีอายุสั้น (เช่น 5-15 นาที) เพื่อลดความเสี่ยงหากถูกขโมยไป
  • ใช้ Refresh Token สำหรับการขอ Access Token ใหม่: เมื่อ Access Token หมดอายุ ใช้ Refresh Token ในการขอ Access Token ใหม่ เพื่อลดความจำเป็นที่ผู้ใช้จะต้องล็อกอินซ้ำบ่อยๆ และ Refresh Token ควรมีอายุยาวนานกว่า Access Token แต่ก็ต้องเก็บรักษาอย่างปลอดภัยที่สุด (เช่น ใน HttpOnly cookies)
  • ตรวจสอบ Claims ทั้งหมดอย่างละเอียด: เมื่อรับ JWT เข้ามา ต้องตรวจสอบ exp, iss, aud, และ Signature เสมอ เพื่อให้แน่ใจว่าโทเค็นถูกต้อง ยังไม่หมดอายุ และมาจากแหล่งที่เชื่อถือได้
  • อย่าเก็บข้อมูลที่ละเอียดอ่อนใน Payload: เนื่องจาก Payload ของ JWS ไม่ได้เข้ารหัส ข้อมูลที่เก็บในนั้นจึงไม่ควรเป็นข้อมูลที่ละเอียดอ่อนมากๆ
  • ป้องกัน Algorithm Confusion Attack: Server ควรระบุอัลกอริทึมที่ยอมรับในการตรวจสอบ JWT อย่างชัดเจน และไม่ควรอนุญาตให้ Client ระบุ alg เป็น “none” หรือยอมรับอัลกอริทึมที่ไม่คาดคิด
  • เก็บ Access Token ในหน่วยความจำ (สำหรับ SPAs) หรือ HttpOnly Cookie (สำหรับ Refresh Token): หลีกเลี่ยงการเก็บ Access Token ใน Local Storage ของ Browser เพื่อป้องกัน XSS attack สำหรับ Refresh Token การใช้ HttpOnly cookie เป็นวิธีที่ปลอดภัยกว่าครับ อ่านเพิ่มเติมเกี่ยวกับ Token Storage
  • มีกลไก Blacklist/Whitelist สำหรับ Revocation (ถ้าจำเป็น): หากต้องการ Revoke JWT ก่อนหมดอายุจริงๆ จะต้องสร้างกลไกเสริม เช่น การเก็บ JWT ID (jti) ที่ถูก Revoke ไว้ใน Blacklist หรือการใช้ Whitelist ของ Active Session

ตารางเปรียบเทียบ: OAuth 2.0 vs. JWT

เพื่อความเข้าใจที่ชัดเจนยิ่งขึ้น นี่คือตารางเปรียบเทียบคุณสมบัติหลักของ OAuth 2.0 และ JWT ครับ

คุณสมบัติ OAuth 2.0 JWT (JSON Web Token)
วัตถุประสงค์หลัก Delegated Authorization (มอบสิทธิ์การเข้าถึงทรัพยากร) Information Representation & Verification (แสดงและยืนยันข้อมูล)
ทำอะไร? เป็นเฟรมเวิร์กที่จัดการกระบวนการให้สิทธิ์แก่ Client เพื่อเข้าถึงทรัพยากรของผู้ใช้โดยไม่ต้องเปิดเผย Credentials เป็นรูปแบบของโทเค็นที่ใช้ในการส่งข้อมูล (Claims) ระหว่างสองฝ่ายอย่างปลอดภัยและตรวจสอบได้ด้วยตัวเอง
เป็นโปรโตคอลหรือไม่? เป็นเฟรมเวิร์ก/โปรโตคอลการอนุญาตสิทธิ์ เป็นรูปแบบข้อมูล (Standard token format)
เกี่ยวข้องกับการยืนยันตัวตน (Authentication)? ไม่โดยตรง แต่เป็นพื้นฐานให้ OpenID Connect (OIDC) ใช้ในการทำ Authentication ใช้ในการยืนยันตัวตน (Authentication) ได้ดีเมื่อเป็นส่วนหนึ่งของ Access Token หรือ ID Token (ใน OIDC)
สถานะ (Stateful/Stateless) เป็น Stateful ในบางส่วน (เช่น การติดตาม Authorization Code) แต่ช่วยให้การเข้าถึงทรัพยากรเป็น Stateless ได้ Stateless (เมื่อออกโทเค็นแล้ว ไม่ต้องเก็บสถานะที่ Server เพื่อตรวจสอบอีก)
ส่วนประกอบหลัก Resource Owner, Client, Authorization Server, Resource Server, Grant Types, Access Token, Refresh Token, Scope Header, Payload (Claims), Signature
ตัวอย่างการใช้งาน “Login with Google”, “Connect with Facebook”, แอปพลิเคชันที่เข้าถึง API ของบริการอื่น Access Token ใน OAuth 2.0, ID Token ใน OpenID Connect, API Key สำหรับ Microservices, Session Token ในเว็บแอปพลิเคชัน
ความสามารถในการ Revoke มีกลไกสำหรับ Revoke Tokens ไม่มีกลไกในตัว ต้องใช้การสร้าง Blacklist/Whitelist เพิ่มเติม

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

ตัวอย่างการนำไปใช้งานจริง (Conceptual)

เรามาลองดูแนวคิดของการนำ OAuth 2.0 และ JWT ไปใช้ในสถานการณ์จริงกันครับ

Web Application (Backend-for-Frontend)

สมมติว่าคุณกำลังพัฒนาเว็บแอปพลิเคชันที่มี Backend (เช่น Node.js/Express, Python/Flask, PHP/Laravel) และต้องการให้ผู้ใช้สามารถล็อกอินด้วยบัญชี Google ได้

  1. Client Registration: คุณลงทะเบียนเว็บแอปของคุณกับ Google Developer Console เพื่อรับ Client ID และ Client Secret กำหนด Redirect URI ของคุณ
  2. Authorization Code Flow:
    • เมื่อผู้ใช้คลิก “Login with Google” เว็บแอปของคุณจะ Redirect ผู้ใช้ไปที่ Google (Authorization Server) พร้อมกับ client_id, redirect_uri, scope (openid profile email), และ state
    • ผู้ใช้ล็อกอินและอนุญาตสิทธิ์บน Google
    • Google Redirect กลับมาที่ redirect_uri ของเว็บแอป พร้อม authorization_code และ state
  3. Token Exchange:
    • Backend ของเว็บแอป (Confidential Client) รับ authorization_code
    • Backend ส่ง authorization_code, client_id, client_secret, redirect_uri ไปยัง Token Endpoint ของ Google
    • Google ตอบกลับด้วย id_token (JWT), access_token (JWT), และ refresh_token
  4. Authentication & Authorization:
    • Backend ตรวจสอบ id_token (JWT) เพื่อยืนยันตัวตนผู้ใช้
    • Backend สร้าง Session ให้ผู้ใช้ (เช่น ด้วย Cookie-based session)
    • Backend เก็บ refresh_token ไว้ใน Database อย่างปลอดภัยเพื่อใช้ขอ Access Token ใหม่ในอนาคต
    • เมื่อ Frontend ต้องการเรียก API จาก Backend, Frontend จะใช้ Cookie ที่ได้รับมา
    • หาก Backend ต้องการเรียก API ของ Google (เช่น Google Calendar API) ในนามของผู้ใช้, Backend จะใช้ access_token (JWT) ที่ได้รับมาครับ

Mobile Application

สำหรับ Mobile Application (iOS/Android) ที่ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัย

  1. Client Registration: ลงทะเบียนแอปกับ Authorization Server (เช่น Google, Facebook, หรือ Identity Provider ของคุณ) เพื่อรับ Client ID
  2. Authorization Code Flow with PKCE:
    • แอป Mobile สร้าง code_verifier และ code_challenge
    • แอป Mobile Redirect ผู้ใช้ไปยัง Authorization Server พร้อม client_id, redirect_uri, scope, response_type=code, state, และ code_challenge
    • ผู้ใช้ล็อกอินและอนุญาตสิทธิ์
    • Authorization Server Redirect กลับมาที่ redirect_uri ของแอป Mobile พร้อม authorization_code
  3. Token Exchange:
    • แอป Mobile ส่ง authorization_code, client_id, redirect_uri, และ code_verifier ไปยัง Token Endpoint ของ Authorization Server (ไม่มี Client Secret)
    • Authorization Server ตอบกลับด้วย id_token (JWT), access_token (JWT), และ refresh_token
  4. Authentication & Authorization:
    • แอป Mobile ตรวจสอบ id_token (JWT) เพื่อยืนยันตัวตนผู้ใช้
    • แอป Mobile ใช้ access_token (JWT) ส่งไปกับทุก API Request ไปยัง Backend ของคุณ
    • Backend ของคุณจะตรวจสอบ access_token (JWT) ที่ได้รับมา เพื่อยืนยันว่าผู้ใช้นี้มีสิทธิ์เข้าถึง API นั้นๆ
    • แอป Mobile อาจเก็บ refresh_token อย่างปลอดภัย (เช่น ใน Keychain/Keystore) เพื่อใช้ขอ Access Token ใหม่เมื่อตัวเก่าหมดอายุ

Machine-to-Machine Communication

สมมติว่าคุณมี Microservice สองตัว (Service A และ Service B) ที่ต้องสื่อสารกัน โดย Service A ต้องการเรียก API ของ Service B

  1. Client Registration: Service A ลงทะเบียนกับ Authorization Server ของคุณ เพื่อรับ Client ID และ Client Secret
  2. Client Credentials Grant:
    • Service A ส่ง client_id และ client_secret ไปยัง Token Endpoint ของ Authorization Server ของคุณ
    • Authorization Server ตอบกลับด้วย access_token (JWT)
  3. API Call:
    • Service A ใช้ access_token (JWT) ที่ได้รับมา ส่งไปกับทุก API Request ไปยัง Service B
    • Service B ตรวจสอบ access_token (JWT) ที่ได้รับมา เพื่อยืนยันว่า Service A มีสิทธิ์เข้าถึง API นั้นๆ

ในทุกๆ ตัวอย่างนี้ Access Token ที่ถูกส่งไปกับ API Request จะเป็น JWT ซึ่งทำให้ Resource Server (หรือ Backend ของคุณ) สามารถตรวจสอบความถูกต้องของโทเค็นได้ด้วยตัวเองอย่างรวดเร็วและมีประสิทธิภาพครับ

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

Q1: OAuth 2.0 คืออะไร และทำไมต้องใช้?

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

Q2: JWT (JSON Web Token) คืออะไร และมีประโยชน์อย่างไร?

A2: JWT คือรูปแบบของโทเค็นที่กะทัดรัดและปลอดภัย ใช้สำหรับแสดงข้อมูลระหว่างสองฝ่ายในรูปแบบ JSON Object ครับ ข้อมูลภายใน JWT สามารถตรวจสอบความถูกต้องได้ด้วย Signature ทำให้มั่นใจได้ว่าข้อมูลไม่ได้ถูกแก้ไขและมาจากผู้ส่งที่เชื่อถือได้ครับ ประโยชน์หลักคือ ช่วยให้ระบบเป็น Stateless (ไม่ต้องเก็บ Session ที่ Server) ทำให้ Scalability ดีขึ้น, มีขนาดเล็ก ส่งผ่าน HTTP ได้ง่าย, และเป็น Self-contained คือมีข้อมูลจำเป็นอยู่ในตัวโทเค็นเลยครับ

Q3: ทำไมต้องใช้ OAuth 2.0 คู่กับ JWT Authentication? ทั้งสองอย่างทำงานร่วมกันอย่างไร?

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

Q4: เราสามารถ Revoke (ยกเลิก) JWT ได้หรือไม่?

A4: โดยธรรมชาติแล้ว JWT เป็น Stateless คือเมื่อถูกออกไปแล้ว Server จะไม่เก็บสถานะของมัน ทำให้การ Revoke JWT ก่อนหมดอายุเป็นเรื่องที่ทำได้ยากครับ อย่างไรก็ตาม หากต้องการฟังก์ชัน Revocation คุณสามารถใช้กลไกเสริมได้ เช่น การสร้าง Blacklist ของ JWT ID (jti claim) ที่ถูก Revoke ไว้ที่ Server หรือการใช้ Whitelist ของ Active Sessions ครับ แต่การทำเช่นนี้จะทำให้คุณสมบัติ Stateless ของ JWT ลดลงและเพิ่มภาระให้กับ Server ครับ สำหรับ Access Token ที่มีอายุสั้น การรอให้หมดอายุเองมักเป็นวิธีปฏิบัติที่เพียงพอครับ ส่วน Refresh Token ที่มีอายุยาวนานกว่า ควรมีการ Revoke ได้ง่ายขึ้นครับ

Q5: ควรเก็บ Access Token และ Refresh Token ที่ไหนใน Web Application (SPA) และ Mobile Application?

A5:

  • สำหรับ Access Token (อายุสั้น):
    • SPA: ควรเก็บไว้ในหน่วยความจำ (in-memory) ของแอปพลิเคชัน เพื่อลดความเสี่ยงจากการโจมตี XSS หากผู้โจมตีเข้าถึง Local Storage ได้
    • Mobile App: เก็บไว้ในหน่วยความจำ หรือ Secure Storage ที่ระบบปฏิบัติการมีให้ (เช่น iOS Keychain, Android Keystore)
  • สำหรับ Refresh Token (อายุยาว):
    • SPA (ถ้ามี Backend): ควรส่ง Refresh Token ไปเก็บที่ Backend ของคุณ และ Backend จัดการการขอ Access Token ใหม่ หรือถ้าจำเป็นต้องเก็บที่ Client จริงๆ ควรใช้ HttpOnly Secure Cookie ครับ
    • Mobile App: เก็บใน Secure Storage ที่ระบบปฏิบัติการมีให้ (เช่น iOS Keychain, Android Keystore) ซึ่งมีความปลอดภัยสูงกว่า Local Storage ของเว็บครับ

สิ่งสำคัญคือไม่ควรเก็บ Access Token หรือ Refresh Token ใน Local Storage ของ Browser ใน SPA เนื่องจากเสี่ยงต่อการถูกโจมตี XSS สูงครับ

Q6: PKCE คืออะไร และทำไมถึงสำคัญ?

A6: PKCE ย่อมาจาก Proof Key for Code Exchange เป็นส่วนเสริมความปลอดภัยสำหรับ OAuth 2.0 Authorization Code Grant โดยเฉพาะสำหรับ Public Clients เช่น Mobile Applications หรือ Single Page Applications (SPAs) ที่ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัย PKCE ช่วยป้องกันการโจมตีประเภท Authorization Code Interception Attack โดยการเพิ่มขั้นตอนที่ Client ต้องสร้าง “code verifier” และ “code challenge” ที่ไม่ซ้ำกันในแต่ละครั้งที่ขอ Code ซึ่งทำให้ผู้โจมตีที่ดักจับ Authorization Code ไปได้ ไม่สามารถนำไปแลกเป็น Access Token ได้ครับ อ่านเพิ่มเติมเกี่ยวกับ PKCE

สรุปและก้าวต่อไป

หวังว่าบทความที่เจาะลึกทั้ง OAuth 2.0 และ JWT Authentication นี้ จะช่วยให้คุณผู้อ่านมีความเข้าใจที่ถ่องแท้และครบถ้วนยิ่งขึ้นเกี่ยวกับสองเทคโนโลยีสำคัญนี้ในโลกของการพัฒนาแอปพลิเคชันยุคใหม่นะครับ

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

ในขณะที่ JWT เป็นรูปแบบของโทเค็นที่กะทัดรัด ปลอดภัย และสามารถยืนยันตัวตนได้ด้วยตัวเอง ทำให้เป็นตัวเลือกที่ยอดเยี่ยมสำหรับการเป็น Access Token และ ID Token ในระบบที่ต้องการความรวดเร็วและ Scalability สูง

เมื่อทั้งสองทำงานร่วมกัน โดยเฉพาะอย่างยิ่งในบริบทของ Open

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

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

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