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

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

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

สารบัญ

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

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

1.1 Authentication คืออะไร?

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

  • ตัวอย่าง: การที่คุณกรอก Username และ Password เพื่อเข้าสู่ระบบ Facebook นั่นคือกระบวนการ Authentication ครับ ระบบจะตรวจสอบว่า Username และ Password ที่คุณให้มาตรงกับข้อมูลที่เก็บไว้หรือไม่ ถ้าตรง ระบบก็จะยืนยันว่าคุณคือเจ้าของบัญชีนั้นจริงๆ
  • วิธีการ: Password, PIN, Biometrics (ลายนิ้วมือ, สแกนใบหน้า), OTP (One-Time Password), Digital Certificates เป็นต้น

1.2 Authorization คืออะไร?

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

  • ตัวอย่าง: หลังจากที่คุณเข้าสู่ระบบ Facebook ได้แล้ว (Authentication), ระบบจะตรวจสอบว่าคุณมีสิทธิ์ในการโพสต์ข้อความ (Authorization), ดูรูปภาพของเพื่อน (Authorization), หรือเข้าถึงข้อมูลส่วนตัวของผู้อื่นได้หรือไม่ (ซึ่งปกติแล้วจะไม่มีสิทธิ์) ครับ
  • วิธีการ: Access Control Lists (ACLs), Role-Based Access Control (RBAC), Policy-Based Access Control (PBAC)

ข้อแตกต่างที่สำคัญ: Authentication คือการพิสูจน์ตัวตน ส่วน Authorization คือการกำหนดสิทธิ์หลังจากที่พิสูจน์ตัวตนแล้วครับ ทั้งสองกระบวนการมักทำงานร่วมกัน แต่มีเป้าหมายที่แตกต่างกันครับ

1.3 ปัญหาดั้งเดิมและทำไมเราถึงต้องการกลไกใหม่

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

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

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

2. เจาะลึก OAuth 2.0: มาตรฐานการอนุญาตสิทธิ์

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

2.1 OAuth 2.0 คืออะไร?

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

OAuth 2.0 ทำงานในลักษณะที่คล้ายกันครับ

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

เป้าหมายหลักคือการมอบอำนาจ (Delegated Authorization) ครับ

2.2 บทบาทหลักใน OAuth 2.0 (Roles)

ในระบบ OAuth 2.0 มีสี่บทบาทหลักที่ทำงานร่วมกันครับ

  1. Resource Owner (เจ้าของทรัพยากร):

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

  2. Client (แอปพลิเคชัน):

    คือแอปพลิเคชันที่ต้องการเข้าถึงทรัพยากรของผู้ใช้ครับ (เช่น แอปพลิเคชันแต่งรูปภาพ)

    • Client จะต้องได้รับการลงทะเบียนกับ Authorization Server ก่อน เพื่อให้ได้รับ Client ID และ Client Secret (ในบางกรณี)
  3. Authorization Server (เซิร์ฟเวอร์อนุญาต):

    เป็นเซิร์ฟเวอร์ที่ทำหน้าที่ตรวจสอบตัวตนของ Resource Owner และเมื่อได้รับการอนุญาตจาก Resource Owner แล้ว จะออก Access Token ให้กับ Client ครับ

    • ทำหน้าที่คล้ายกับคนดูแลบ้านที่ตรวจสอบจดหมายอนุญาต
  4. Resource Server (เซิร์ฟเวอร์ทรัพยากร):

    เป็นเซิร์ฟเวอร์ที่เก็บข้อมูลหรือทรัพยากรที่ได้รับการป้องกันครับ (เช่น Google Photos API ที่เก็บรูปภาพของคุณ)

    • จะทำการตรวจสอบ Access Token ที่ Client ส่งมา เพื่อยืนยันว่า Client มีสิทธิ์เข้าถึงทรัพยากรที่ร้องขอหรือไม่

2.3 แนวคิดสำคัญใน OAuth 2.0

  • Access Token:

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

  • Refresh Token:

    เป็นโทเค็นที่มีอายุยาวนานกว่า Access Token ครับ ใช้เพื่อขอ Access Token ใหม่เมื่อ Access Token เดิมหมดอายุ โดยไม่ต้องให้ผู้ใช้ต้องทำการอนุญาตซ้ำอีกครั้งครับ การใช้ Refresh Token ช่วยลดความจำเป็นในการจัดเก็บ Access Token ที่มีอายุยาวนาน ซึ่งมีความเสี่ยงสูงกว่าครับ

  • Scopes:

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

  • Client ID:

    เป็นตัวระบุสาธารณะที่ไม่ซ้ำกันสำหรับ Client ที่ลงทะเบียนกับ Authorization Server ครับ

  • Client Secret:

    เป็นความลับที่ใช้ร่วมกันระหว่าง Client และ Authorization Server ใช้เพื่อยืนยันตัวตนของ Client ครับ Client Secret จะต้องเก็บไว้อย่างปลอดภัยและไม่ควรเปิดเผยต่อสาธารณะครับ (สำหรับ Confidential Clients)

  • Redirect URI:

    คือ URL ที่ Authorization Server จะส่งผู้ใช้กลับมาหลังจากที่ผู้ใช้ทำการยืนยันตัวตนและอนุญาตสิทธิ์เสร็จสิ้นครับ การตรวจสอบ Redirect URI อย่างเคร่งครัดเป็นสิ่งสำคัญเพื่อป้องกันการโจมตีแบบ Phishing ครับ

2.4 ประเภทของการให้สิทธิ์ (Grant Types/Authorization Flows)

OAuth 2.0 มี Grant Types หรือ Flow ที่แตกต่างกันหลายแบบ เพื่อรองรับสถานการณ์การใช้งานที่หลากหลายครับ แต่ละแบบมีข้อดี ข้อเสีย และระดับความปลอดภัยที่แตกต่างกันครับ

2.4.1 Authorization Code Grant

นี่คือ Grant Type ที่นิยมใช้มากที่สุดและปลอดภัยที่สุดสำหรับแอปพลิเคชันเว็บฝั่งเซิร์ฟเวอร์ (Confidential Clients) ครับ เพราะว่า Client Secret สามารถเก็บไว้ได้อย่างปลอดภัยบนเซิร์ฟเวอร์

ขั้นตอนการทำงาน:

  1. ผู้ใช้เริ่มกระบวนการ: Client ส่งผู้ใช้ไปยัง Authorization Server พร้อม Client ID, Redirect URI, Scope และ State.

    GET /authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=read_profile&state=xyz
    Host: authorization-server.com
  2. การยืนยันตัวตนและการอนุญาต: ผู้ใช้เข้าสู่ระบบที่ Authorization Server (ถ้ายังไม่ได้เข้าสู่ระบบ) และให้ความยินยอม (Consent) ในการให้สิทธิ์แก่ Client ครับ
  3. ส่ง Authorization Code: Authorization Server ส่งผู้ใช้กลับไปยัง Redirect URI ของ Client พร้อมกับ Authorization Code และ State ที่ตรงกันครับ

    GET /callback?code=AUTH_CODE_FROM_SERVER&state=xyz
    Host: your-client-app.com
  4. แลกเปลี่ยน Code เป็น Token: Client (จากฝั่งเซิร์ฟเวอร์) ส่ง Authorization Code, Client ID, Client Secret และ Redirect URI ไปยัง Authorization Server เพื่อขอ Access Token และ Refresh Token ครับ การแลกเปลี่ยนนี้เกิดขึ้นแบบ Back-channel (ระหว่างเซิร์ฟเวอร์กับเซิร์ฟเวอร์) จึงปลอดภัยครับ

    POST /token
    Content-Type: application/x-www-form-urlencoded
    Host: authorization-server.com
    
    grant_type=authorization_code&code=AUTH_CODE_FROM_SERVER&redirect_uri=YOUR_REDIRECT_URI&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET
  5. รับ Access Token: Authorization Server ตรวจสอบข้อมูลและตอบกลับด้วย Access Token (และ Refresh Token) ครับ

    {
      "access_token": "YOUR_ACCESS_TOKEN",
      "token_type": "Bearer",
      "expires_in": 3600,
      "refresh_token": "YOUR_REFRESH_TOKEN",
      "scope": "read_profile"
    }
  6. เข้าถึงทรัพยากร: Client ใช้ Access Token เพื่อเรียกใช้ API ของ Resource Server ครับ

    GET /api/user/profile
    Authorization: Bearer YOUR_ACCESS_TOKEN
    Host: resource-server.com

2.4.2 Authorization Code Grant with PKCE (Proof Key for Code Exchange)

เป็นส่วนเสริมของ Authorization Code Grant ที่ออกแบบมาเพื่อเพิ่มความปลอดภัยสำหรับ Public Clients (เช่น Single Page Applications (SPAs) หรือ Mobile Apps) ที่ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัยครับ

ทำไมต้องมี PKCE?

เนื่องจาก SPAs และ Mobile Apps ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัย (เพราะโค้ดสามารถถูกตรวจสอบได้ง่าย) หากใช้ Authorization Code Grant แบบปกติ โค้ดที่ได้มาอาจถูกขโมยไปใช้แลกเป็น Access Token ได้ครับ PKCE เข้ามาแก้ปัญหานี้โดยการเพิ่ม “ความลับ” แบบครั้งเดียวในการแลกเปลี่ยน Code ครับ

ขั้นตอนการทำงาน (เพิ่มเติมจาก Authorization Code Grant):

  1. สร้าง Code Verifier และ Code Challenge: Client สร้างสตริงสุ่มที่เรียกว่า Code Verifier และแปลงเป็น Code Challenge โดยใช้ฟังก์ชันแฮช (เช่น SHA256) ก่อนที่จะส่งผู้ใช้ไปยัง Authorization Server
  2. ส่ง Code Challenge: Client ส่งผู้ใช้ไปยัง Authorization Server พร้อม Client ID, Redirect URI, Scope, State และ Code Challenge ครับ

    GET /authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=read_profile&state=xyz&code_challenge=CODE_CHALLENGE_FROM_CLIENT&code_challenge_method=S256
    Host: authorization-server.com
  3. แลกเปลี่ยน Code เป็น Token: เมื่อ Client ได้รับ Authorization Code กลับมา จะส่ง Authorization Code, Client ID, Redirect URI และ Code Verifier (ที่สร้างไว้ในตอนแรก) ไปยัง Authorization Server

    POST /token
    Content-Type: application/x-www-form-urlencoded
    Host: authorization-server.com
    
    grant_type=authorization_code&code=AUTH_CODE_FROM_SERVER&redirect_uri=YOUR_REDIRECT_URI&client_id=YOUR_CLIENT_ID&code_verifier=CODE_VERIFIER_FROM_CLIENT
  4. การตรวจสอบ PKCE: Authorization Server จะใช้ Code Verifier ที่ได้รับมาสร้าง Code Challenge ขึ้นมาใหม่ และเปรียบเทียบกับ Code Challenge ที่ได้รับมาในขั้นตอนแรก หากตรงกัน จึงจะออก Access Token ให้ครับ

PKCE ช่วยให้มั่นใจว่าเฉพาะ Client ที่เริ่มต้นกระบวนการเท่านั้นที่สามารถแลกเปลี่ยน Authorization Code เป็น Access Token ได้ครับ

2.4.3 Client Credentials Grant

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

  • ตัวอย่าง: ระบบหลังบ้านที่ต้องการเรียกใช้ API ของบริการอื่นเพื่อดึงข้อมูลสถิติ

    POST /token
    Content-Type: application/x-www-form-urlencoded
    Host: authorization-server.com
    
    grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=read_stats

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

Client ขอ Username และ Password ของผู้ใช้โดยตรง แล้วส่งไปที่ Authorization Server เพื่อแลกเป็น Access Token ครับ

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

2.4.5 Implicit Grant (ไม่แนะนำ/ล้าสมัย)

Client จะได้รับ Access Token โดยตรงหลังจากที่ผู้ใช้อนุญาตสิทธิ์ โดยไม่มีการแลกเปลี่ยน Code ครับ เคยนิยมใช้กับ SPAs แต่ปัจจุบันถูกพิจารณาว่าไม่ปลอดภัยและถูกแทนที่ด้วย Authorization Code Grant with PKCE ครับ

  • ปัญหา: Access Token จะปรากฏใน URL Fragment ซึ่งอาจถูกดักจับได้ง่าย และไม่มี Refresh Token ทำให้ต้องขอ Access Token ใหม่บ่อยๆ ครับ

2.5 ข้อควรระวังด้านความปลอดภัยสำหรับ OAuth 2.0

  • Validate Redirect URI อย่างเคร่งครัด: ตรวจสอบให้แน่ใจว่า Redirect URI ที่ส่งมาตรงกับที่ลงทะเบียนไว้กับ Authorization Server เพื่อป้องกันการโจมตีแบบ Phishing หรือการเปลี่ยนเส้นทางไปยังเว็บไซต์อันตรายครับ
  • ใช้ State Parameter: ใช้พารามิเตอร์ state เพื่อป้องกันการโจมตีแบบ CSRF (Cross-Site Request Forgery) โดยการสร้างค่าสุ่มที่ไม่ซ้ำกันในแต่ละคำขอและตรวจสอบว่าค่าที่ส่งกลับมาตรงกันหรือไม่ครับ
  • ปกป้อง Client Secret: สำหรับ Confidential Clients, Client Secret จะต้องเก็บไว้อย่างปลอดภัยบนเซิร์ฟเวอร์เท่านั้น ห้ามเปิดเผยในโค้ดฝั่ง Client (Frontend) โดยเด็ดขาดครับ
  • ใช้ HTTPS เสมอ: การสื่อสารทั้งหมดระหว่าง Client, Authorization Server และ Resource Server จะต้องผ่าน HTTPS เพื่อเข้ารหัสข้อมูลและป้องกันการดักจับข้อมูลครับ
  • กำหนดอายุของ Token: Access Token ควรกำหนดอายุการใช้งานที่สั้นเพื่อลดความเสี่ยงหาก Access Token ถูกขโมย และใช้ Refresh Token ในการขอ Access Token ใหม่แทนครับ
  • ใช้ PKCE สำหรับ Public Clients: สำหรับ SPAs และ Mobile Apps ควรกำหนดให้ใช้ Authorization Code Grant with PKCE เสมอครับ

หากคุณต้องการศึกษาเพิ่มเติมเกี่ยวกับ OAuth 2.0 ในเชิงลึก อ่านเพิ่มเติมได้ที่นี่ ครับ

3. ทำความเข้าใจกับ JSON Web Tokens (JWT)

หลังจากที่เราเข้าใจ OAuth 2.0 ซึ่งเป็นเฟรมเวิร์กสำหรับการอนุญาตสิทธิ์แล้ว เรามาทำความรู้จักกับ JWT ซึ่งเป็นรูปแบบ (format) ที่นิยมใช้ในการสร้าง Access Token หรือ Identity Token ในระบบ OAuth 2.0 และ OpenID Connect ครับ

3.1 JWT คืออะไร?

JSON Web Token (JWT) คือมาตรฐานเปิด (RFC 7519) ที่ใช้ในการส่งข้อมูลระหว่างสองฝ่ายได้อย่างปลอดภัย โดยข้อมูลที่ส่งไปนั้นเป็นแบบ Compact และ URL-safe ครับ JWT มักใช้สำหรับการยืนยันตัวตน (Authentication) และการอนุญาต (Authorization) โดยเฉพาะในระบบ API ที่ต้องการความไร้สถานะ (Stateless) ครับ

สิ่งสำคัญที่ต้องจำคือ JWT ไม่ได้เป็น Protocol เหมือน OAuth 2.0 แต่เป็นเพียงรูปแบบข้อมูล (Token format) ที่ใช้ในการบรรจุ “claims” หรือข้อมูลเกี่ยวกับผู้ใช้และสิทธิ์ต่างๆ ครับ

3.2 โครงสร้างของ JWT (Header, Payload, Signature)

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

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

แต่ละส่วนจะถูกเข้ารหัสด้วย Base64Url ครับ

3.2.1 Header

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

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

ตัวอย่าง Header (ก่อนเข้ารหัส Base64Url):

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

3.2.2 Payload (Claims)

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

  1. Registered Claims:

    เป็น Claims ที่กำหนดไว้ล่วงหน้าโดยมาตรฐาน JWT แต่ไม่ได้บังคับให้ใช้ทั้งหมดครับ เป็นคำแนะนำเพื่อความเข้ากันได้

    • 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 ที่สามารถกำหนดเองได้ แต่ควรระมัดระวังไม่ให้ชื่อ Claim ซ้ำกับ Registered Claims ครับ

  3. Private Claims:

    เป็น Claims ที่กำหนดเองสำหรับข้อตกลงระหว่างสองฝ่ายที่ใช้ JWT โดยเฉพาะครับ

ตัวอย่าง Payload (ก่อนเข้ารหัส Base64Url):

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1516239022,
  "exp": 1516242622 // หมดอายุใน 1 ชั่วโมง
}

3.2.3 Signature

ส่วน Signature ใช้ในการตรวจสอบว่า Token ไม่ได้ถูกเปลี่ยนแปลงระหว่างทาง และมาจากผู้ออก Token ที่แท้จริงครับ การสร้าง Signature จะใช้ Header ที่เข้ารหัส Base64Url, Payload ที่เข้ารหัส Base64Url และ Secret Key ที่รู้กันระหว่างผู้ออก (เช่น Authorization Server) และผู้ตรวจสอบ (เช่น Resource Server) ครับ

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

หากไม่มี Signature หรือ Signature ไม่ถูกต้อง Token นั้นจะถือว่าไม่น่าเชื่อถือครับ

3.3 การใช้งาน JWT

JWT ถูกนำไปใช้ในหลายบริบทครับ

  • Authentication:

    เมื่อผู้ใช้เข้าสู่ระบบได้สำเร็จ เซิร์ฟเวอร์จะสร้าง JWT และส่งกลับไปให้ Client ครับ Client จะจัดเก็บ JWT นั้นไว้ (เช่น ใน Local Storage, Session Storage หรือ Cookie) และส่ง JWT นี้ไปกับทุกๆ คำขอไปยัง Resource Server เพื่อยืนยันตัวตนของผู้ใช้ครับ

  • Authorization:

    Resource Server สามารถตรวจสอบ Claims ใน JWT เพื่อตัดสินใจว่าผู้ใช้มีสิทธิ์เข้าถึงทรัพยากรที่ร้องขอหรือไม่ โดยไม่ต้องเรียกกลับไปยัง Authorization Server ในทุกๆ คำขอครับ

  • Information Exchange:

    JWT สามารถใช้ในการแลกเปลี่ยนข้อมูลระหว่างระบบได้อย่างปลอดภัย เนื่องจากข้อมูลถูกลงนามด้วย Digital Signature ครับ

3.4 ข้อดีของ JWT

  • Statelessness (ไร้สถานะ):

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

  • Compactness:

    JWT มีขนาดเล็กและสามารถส่งผ่าน URL, POST parameter หรือภายใน HTTP header ได้อย่างง่ายดาย ทำให้มีประสิทธิภาพในการส่งข้อมูลครับ

  • Self-contained:

    เนื่องจาก Payload มีข้อมูลที่ครบถ้วน Resource Server สามารถตรวจสอบ Token ได้ด้วยตัวเอง โดยไม่ต้องไปสอบถามฐานข้อมูลหรือ Authorization Server ซ้ำในทุกๆ คำขอ (หลังจากที่ตรวจสอบ Signature แล้ว) ครับ

  • Security:

    ด้วยการใช้ Digital Signature ทำให้มั่นใจได้ว่าข้อมูลใน Token ไม่ได้ถูกแก้ไขระหว่างทาง และมาจากผู้ออกที่เชื่อถือได้ครับ

3.5 ข้อเสียและข้อควรระวังด้านความปลอดภัยของ JWT

  • ไม่มีกลไกการเพิกถอน (Revocation) ในตัว:

    เมื่อ JWT ถูกออกไปแล้ว จะยังคงใช้งานได้จนกว่าจะหมดอายุครับ หาก Access Token ถูกขโมย ผู้โจมตีสามารถใช้ Token นั้นได้จนกว่าจะหมดอายุ ระบบจะต้องมีกลไกเพิ่มเติมในการจัดการการเพิกถอน เช่น การสร้าง Blacklist หรือการกำหนดอายุ Token ให้สั้นมากแล้วใช้ Refresh Token เข้ามาช่วยครับ

  • ขนาดของ Payload:

    หากใส่ข้อมูลใน Payload มากเกินไป จะทำให้ Token มีขนาดใหญ่ขึ้นและส่งผลต่อประสิทธิภาพในการสื่อสารได้ครับ

  • ความเสี่ยงต่อ XSS:

    หากจัดเก็บ JWT ไว้ใน Local Storage ของเบราว์เซอร์ อาจเสี่ยงต่อการถูกโจมตีแบบ XSS (Cross-Site Scripting) หากมีช่องโหว่ในเว็บไซต์ ผู้โจมตีสามารถขโมย JWT ไปใช้งานได้ครับ

  • Secret Key ต้องปลอดภัย:

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

  • Always use HTTPS:

    เช่นเดียวกับ OAuth 2.0 การส่ง JWT จะต้องผ่าน HTTPS เสมอ เพื่อป้องกันการดักจับข้อมูลระหว่างทางครับ

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

เราจะใช้ไลบรารี PyJWT ใน Python ครับ

# ติดตั้ง: pip install PyJWT
import jwt
import datetime
import time

# Secret Key ที่ใช้ในการลงนาม JWT (ควรเก็บเป็นความลับสุดยอด)
SECRET_KEY = "your-very-secret-key-that-no-one-should-know"

# 1. การสร้าง JWT
def create_jwt(user_id, username, is_admin=False):
    payload = {
        "user_id": user_id,
        "username": username,
        "admin": is_admin,
        "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1), # หมดอายุใน 1 ชั่วโมง
        "iat": datetime.datetime.utcnow(),                              # เวลาที่สร้าง
        "iss": "siamlancard.com"                                        # ผู้ออก
    }
    # เข้ารหัส JWT ด้วยอัลกอริทึม HS256
    encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
    return encoded_jwt

# 2. การตรวจสอบ JWT
def verify_jwt(token):
    try:
        # ถอดรหัสและตรวจสอบ Signature
        decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        print("JWT Verified Successfully!")
        print("Payload:", decoded_payload)
        return decoded_payload
    except jwt.ExpiredSignatureError:
        print("JWT has expired!")
        return None
    except jwt.InvalidTokenError as e:
        print(f"Invalid JWT: {e}")
        return None

# --- ตัวอย่างการใช้งาน ---
if __name__ == "__main__":
    print("--- Creating JWT ---")
    user_id = 123
    username = "testuser"
    is_admin = True
    
    token = create_jwt(user_id, username, is_admin)
    print(f"Generated JWT: {token}\n")

    print("--- Verifying JWT ---")
    verified_data = verify_jwt(token)
    
    if verified_data:
        print(f"User ID from token: {verified_data['user_id']}")
        print(f"Username from token: {verified_data['username']}")
        print(f"Is Admin: {verified_data['admin']}\n")

    # ลองทดสอบ JWT ที่หมดอายุ (โดยการสร้าง JWT ที่หมดอายุทันที)
    print("--- Testing Expired JWT ---")
    expired_payload = {
        "user_id": 999,
        "username": "expired_user",
        "exp": datetime.datetime.utcnow() - datetime.timedelta(seconds=1), # หมดอายุไปแล้ว
        "iat": datetime.datetime.utcnow(),
        "iss": "siamlancard.com"
    }
    expired_token = jwt.encode(expired_payload, SECRET_KEY, algorithm="HS256")
    print(f"Generated Expired JWT: {expired_token}\n")
    verify_jwt(expired_token)
    
    # ลองทดสอบ JWT ที่มี Secret Key ไม่ถูกต้อง
    print("\n--- Testing Invalid Secret Key ---")
    invalid_secret_key = "wrong-secret"
    try:
        jwt.decode(token, invalid_secret_key, algorithms=["HS256"])
    except jwt.InvalidSignatureError:
        print("Caught expected InvalidSignatureError: Signature verification failed with wrong secret key.")
    except Exception as e:
        print(f"Caught unexpected error: {e}")

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

4. การผสานรวม OAuth 2.0 และ JWT เข้าด้วยกัน

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

4.1 บทบาทที่เสริมกัน

  • OAuth 2.0: เป็น เฟรมเวิร์ก (framework) ที่กำหนดวิธีการที่ Client จะได้รับ Access Token จาก Authorization Server โดยที่ผู้ใช้ไม่ต้องเปิดเผยรหัสผ่านครับ มันคือ “กระบวนการ” ในการขอและมอบสิทธิ์
  • JWT: เป็น รูปแบบ (format) ที่นิยมใช้ในการสร้าง Access Token (และ Refresh Token หรือ ID Token ใน OpenID Connect) ครับ มันคือ “วิธีการ” ที่ใช้บรรจุข้อมูลใน Token นั้นๆ ครับ

กล่าวคือ OAuth 2.0 คือโปรโตคอลการอนุญาตที่บอกว่า “จะขอ Access Token ได้อย่างไร” และ JWT คือมาตรฐานที่บอกว่า “Access Token นั้นควรมีหน้าตาและข้อมูลอะไรบ้าง” ครับ

4.2 Workflow การทำงานร่วมกัน

นี่คือขั้นตอนทั่วไปเมื่อ OAuth 2.0 และ JWT ทำงานร่วมกันในระบบหนึ่งครับ

  1. ผู้ใช้เริ่มต้นกระบวนการอนุญาต:

    Client (แอปพลิเคชัน) ส่งผู้ใช้ไปยัง Authorization Server เพื่อขอสิทธิ์การเข้าถึงทรัพยากรบางอย่าง (ตามขั้นตอนของ OAuth 2.0 Grant Type เช่น Authorization Code Grant with PKCE)

  2. ผู้ใช้อนุญาต:

    ผู้ใช้เข้าสู่ระบบและให้ความยินยอม (Consent) แก่ Client ในการเข้าถึงข้อมูลตาม Scope ที่ร้องขอ

  3. Authorization Server ออก Token (ที่เป็น JWT):

    เมื่อผู้ใช้อนุญาตสำเร็จ Authorization Server จะออก Access Token (และอาจรวมถึง Refresh Token ด้วย) โดย Access Token นั้นมักจะเป็น JWT ครับ โดย JWT นั้นจะบรรจุ Claims ต่างๆ เช่น User ID, Scope ที่ได้รับอนุญาต, เวลาหมดอายุ (exp) และลงนามด้วย Secret Key ของ Authorization Server

    {
      "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE2NzgyNjQ4MDB9.SIGNATURE",
      "token_type": "Bearer",
      "expires_in": 3600,
      "refresh_token": "SOME_LONG_LIVED_REFRESH_TOKEN",
      "scope": "read_profile"
    }
  4. Client ส่ง JWT (Access Token) ไปยัง Resource Server:

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

    GET /api/user/profile
    Host: resource-server.com
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE2NzgyNjQ4MDB9.SIGNATURE
  5. Resource Server ตรวจสอบ JWT:

    Resource Server จะรับ JWT มาและทำการตรวจสอบ

    • ตรวจสอบ Signature: เพื่อยืนยันว่า Token ไม่ได้ถูกแก้ไขและมาจาก Authorization Server ที่เชื่อถือได้ (โดยใช้ Secret Key หรือ Public Key ที่รู้กัน)
    • ตรวจสอบ Claims: ตรวจสอบ exp (หมดอายุหรือยัง), iss (ผู้ออกถูกต้องหรือไม่), aud (สำหรับใคร), และ Scope ที่ระบุใน Token เพื่อดูว่าผู้ใช้มีสิทธิ์เข้าถึงทรัพยากรที่ร้องขอหรือไม่
  6. Resource Server ตอบกลับ:

    หาก JWT ถูกต้องและมีสิทธิ์ Resource Server จะประมวลผลคำขอและส่งข้อมูลกลับไปให้ Client ครับ

การทำงานร่วมกันนี้ทำให้ระบบมีประสิทธิภาพและ Scalability สูง เพราะ Resource Server ไม่จำเป็นต้องตรวจสอบกับ Authorization Server ทุกครั้งที่ได้รับคำขอ API เพียงแค่ตรวจสอบ JWT ด้วยตัวเองก็พอแล้วครับ (Statelessness ของ JWT)

5. การเลือกใช้และ Best Practices

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

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

  • เมื่อแอปพลิเคชันต้องการเข้าถึงข้อมูลของผู้ใช้จากบริการอื่น:

    นี่คือกรณีการใช้งานหลักของ OAuth 2.0 ครับ เช่น การเข้าสู่ระบบด้วย Google, Facebook, Twitter หรือการอนุญาตให้แอปพลิเคชันจัดการรูปภาพเข้าถึง Google Photos ของคุณครับ

  • เมื่อคุณต้องการมอบสิทธิ์ (Delegated Authorization) โดยไม่ต้องเปิดเผยรหัสผ่าน:

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

  • เมื่อคุณพัฒนา API ที่มีผู้ใช้งานหลาย Client (Third-party applications):

    OAuth 2.0 เป็นมาตรฐานที่ช่วยให้การจัดการสิทธิ์การเข้าถึง API เป็นไปอย่างมีระบบและปลอดภัยครับ

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

  • สำหรับการยืนยันตัวตนและการอนุญาตในระบบ API แบบ Stateless:

    JWT เหมาะอย่างยิ่งสำหรับ Microservices หรือ API Gateway ที่ต้องการลดภาระการจัดการ Session State ครับ

  • เมื่อต้องการส่งข้อมูลระหว่างบริการที่เชื่อถือกัน:

    JWT สามารถใช้เป็นรูปแบบในการแลกเปลี่ยนข้อมูลที่ลงนามแล้ว เพื่อยืนยันแหล่งที่มาของข้อมูลครับ

  • เป็นรูปแบบของ Access Token ใน OAuth 2.0 และ ID Token ใน OpenID Connect:

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

  • เมื่อต้องการลดภาระการค้นหาข้อมูลจากฐานข้อมูลในทุกๆ คำขอ:

    เนื่องจาก JWT มีข้อมูล (Claims) บรรจุอยู่ภายใน ทำให้ Resource Server สามารถตัดสินใจเรื่องสิทธิ์ได้ทันทีครับ

5.3 Best Practices สำหรับ OAuth 2.0

  • เลือก Grant Type ที่เหมาะสม:

    • สำหรับ Web Applications (Server-side): ใช้ Authorization Code Grant
    • สำหรับ SPAs และ Mobile Apps (Public Clients): ใช้ Authorization Code Grant with PKCE เสมอ
    • สำหรับ Machine-to-Machine Communication: ใช้ Client Credentials Grant
    • หลีกเลี่ยง Resource Owner Password Credentials Grant และ Implicit Grant
  • Validate Redirect URIs อย่างเคร่งครัด:

    ลงทะเบียน Redirect URI ที่ถูกต้องและจำกัดให้แคบที่สุดเท่าที่จะทำได้ครับ

  • ใช้ State Parameter:

    สร้างค่าสุ่มที่ไม่ซ้ำกันสำหรับทุกคำขอ Authorization และตรวจสอบเมื่อได้รับ Callback กลับมา เพื่อป้องกัน CSRF ครับ

  • ปกป้อง Client Secret:

    สำหรับ Confidential Clients, Client Secret จะต้องเก็บไว้อย่างปลอดภัยและไม่เปิดเผยต่อสาธารณะหรือฝั่ง Client ครับ

  • ใช้ HTTPS เสมอ:

    การสื่อสารทั้งหมดต้องเข้ารหัสด้วย TLS/SSL ครับ

  • กำหนด Scope ที่แคบที่สุด:

    ขอ Scope ที่จำเป็นต่อการทำงานของแอปพลิเคชันเท่านั้น เพื่อลดความเสี่ยงหาก Access Token ถูกขโมยไปครับ

  • จัดการ Refresh Token อย่างปลอดภัย:

    Refresh Token ควรกำหนดอายุที่ยาวนานกว่า Access Token และควรเก็บไว้อย่างปลอดภัย (เช่น ใน HttpOnly Cookie สำหรับเว็บ) และมีกลไกในการเพิกถอนได้ทันทีหากสงสัยว่าถูกขโมยครับ

5.4 Best Practices สำหรับ JWT

  • กำหนดอายุ Token ให้สั้น:

    Access Token ควรมีอายุการใช้งานที่สั้น (เช่น 15-60 นาที) เพื่อลดความเสี่ยงหากถูกขโมยไปครับ

  • ใช้ Refresh Token คู่กับ Access Token:

    เพื่อให้ผู้ใช้ไม่ต้องล็อกอินใหม่บ่อยๆ เมื่อ Access Token หมดอายุ

  • เก็บ Secret Key ให้เป็นความลับสุดยอด:

    Secret Key ที่ใช้ลงนาม JWT เป็นกุญแจสำคัญในการรักษาความปลอดภัย ห้ามเปิดเผยเด็ดขาดครับ

  • ใช้ HTTPS เสมอ:

    เพื่อป้องกันการดักจับ JWT ระหว่างการส่งผ่านเครือข่าย

  • เก็บ JWT อย่างปลอดภัยใน Client-side:

    • สำหรับ Web:
      • HttpOnly Cookie: เป็นวิธีที่ปลอดภัยที่สุดสำหรับ Access Token (หากไม่ต้องการเข้าถึงจาก JavaScript) หรือ Refresh Token เพราะป้องกัน XSS ได้ดีกว่า
      • Memory (RAM): เก็บในหน่วยความจำของแอปพลิเคชันสำหรับ Access Token ที่ต้องการเข้าถึงด้วย JavaScript แต่ต้องแน่ใจว่าลบออกเมื่อปิดหน้าต่าง/แท็บ
      • หลีกเลี่ยง Local Storage: มีความเสี่ยงต่อ XSS สูงครับ
    • สำหรับ Mobile Apps: ใช้ Secure Storage ที่จัดหาโดยแพลตฟอร์ม (เช่น Keychain บน iOS, KeyStore บน Android)
  • Implement Token Revocation (ถ้าจำเป็น):

    หากระบบของคุณต้องการความสามารถในการเพิกถอน Access Token ทันที (เช่น ผู้ใช้ออกจากระบบ) คุณอาจต้องมี Blacklist สำหรับ JWT ที่ยังไม่หมดอายุ หรือใช้กลไกที่เรียกว่า “Short-lived tokens + Revocation List” ครับ

  • ตรวจสอบ Claims ทั้งหมด:

    เมื่อ Resource Server ได้รับ JWT ต้องตรวจสอบ exp, iss, aud และ Claims อื่นๆ ที่จำเป็นอย่างละเอียดครับ

  • อย่าใส่ข้อมูลที่ละเอียดอ่อนเกินไปใน Payload:

    Payload ของ JWT ไม่ได้ถูกเข้ารหัส เพียงแต่ถูกลงนามเท่านั้น (Signed) ดังนั้นข้อมูลใน Payload สามารถอ่านได้โดยใครก็ตามที่มี Token นั้น ควรใส่เฉพาะข้อมูลที่ไม่เป็นความลับและจำเป็นต่อการอนุญาตเท่านั้นครับ

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

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

คุณสมบัติ OAuth 2.0 JSON Web Token (JWT)
ประเภท/หน้าที่หลัก เฟรมเวิร์กสำหรับการ อนุญาตสิทธิ์ (Authorization) รูปแบบ (Format) ของ โทเค็น สำหรับการส่งข้อมูลที่ลงนาม
บทบาทหลัก มอบสิทธิ์ให้ Client เข้าถึงทรัพยากรของผู้ใช้บน Resource Server โดยไม่ต้องเปิดเผยรหัสผ่าน ใช้เป็น Access Token หรือ Identity Token เพื่อยืนยันตัวตน/สิทธิ์แบบ Stateless
เป็น Protocol? ใช่ (Authorization Protocol) ไม่ (เป็นแค่รูปแบบข้อมูล)
ความซับซ้อน ซับซ้อนกว่า มีหลายบทบาทและขั้นตอนการทำงาน (Grant Types) ค่อนข้างตรงไปตรงมา: Header, Payload, Signature
การจัดการสถานะ (State) โดยตัวมันเองเป็นการจัดการสิทธิ์ (Delegated Authorization) ซึ่งอาจมีสถานะในช่วง Flow การขอ Token ออกแบบมาให้ ไร้สถานะ (Stateless) เพื่อความ Scalability
ข้อมูลที่เกี่ยวข้อง Authorization Code, Access Token, Refresh Token, Client ID, Client Secret, Redirect URI, Scopes Header, Payload (Claims), Signature, Secret Key/Public Key
การใช้งานทั่วไป ลงชื่อเข้าใช้ด้วยบริการภายนอก (Sign in with Google/Facebook), การเข้าถึง API ของบริการอื่น API Authorization, Single Sign-On (SSO), การแลกเปลี่ยนข้อมูลระหว่างบริการ
ความเสี่ยงด้านความปลอดภัยหลัก Phishing, CSRF, Token Leakage, การตั้งค่า Redirect URI ไม่ถูกต้อง Token leakage (XSS), Secret Key รั่วไหล, Payload ใหญ่เกินไป, ไม่มีกลไก Revocation ในตัว
ทำงานร่วมกันหรือไม่? บ่อยครั้งที่ทำงานร่วมกัน: OAuth 2.0 ใช้ JWT เป็นรูปแบบของ Access Token เพื่อให้ Resource Server ตรวจสอบสิทธิ์ได้แบบ Stateless

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

Q1: OAuth 2.0 กับ OpenID Connect (OIDC) แตกต่างกันอย่างไร?

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

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

Q2: JWT ปลอดภัยจริงหรือ? มีวิธีป้องกันการโจมตีอย่างไร?

A2: JWT มีความปลอดภัยในแง่ที่ว่ามันป้องกันการปลอมแปลงและแก้ไขข้อมูลได้ด้วย Digital Signature ครับ แต่ความปลอดภัยของ JWT ขึ้นอยู่กับการใช้งานที่ถูกต้องครับ ข้อควรระวังและการป้องกันมีดังนี้ครับ:

  • เก็บ Secret Key ให้เป็นความลับสุดยอด: หาก Key รั่วไหล ผู้โจมตีสามารถสร้าง JWT ปลอมได้
  • ใช้ HTTPS เสมอ: เพื่อป้องกันการดักจับ Token ระหว่างการส่ง
  • เก็บ JWT ใน Client-side อย่างปลอดภัย: หลีกเลี่ยง Local Storage สำหรับ Access Token ที่มีความสำคัญสูง ควรใช้ HttpOnly Cookie หรือ Memory (สำหรับ SPAs)
  • กำหนดอายุ Token ให้สั้น: ลดความเสียหายหาก Token ถูกขโมย
  • ใช้ Refresh Token: สำหรับการต่ออายุ Access Token
  • มีกลไก Revocation: หากจำเป็นต้องเพิกถอน Token ทันที
  • อย่าใส่ข้อมูลที่ละเอียดอ่อนใน Payload: เพราะ Payload ถูกเข้ารหัส Base64Url ซึ่งสามารถอ่านได้ง่าย ไม่ใช่การเข้ารหัสแบบซ่อนข้อมูลครับ

Q3: ควรเก็บ JWT (Access Token) ไว้ที่ไหนใน Frontend (เช่น Web Browser)?

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

  • HttpOnly Cookie:

    เป็นตัวเลือกที่ปลอดภัยที่สุดสำหรับป้องกัน XSS เพราะ JavaScript ไม่สามารถเข้าถึงได้โดยตรงครับ เหมาะสำหรับ Access Token ที่ส่งไปกับทุกๆ คำขอ หรือ Refresh Token ครับ

  • Memory (RAM):

    เก็บในตัวแปร JavaScript ภายในแอปพลิเคชัน สำหรับ Access Token ที่ต้องเข้าถึงด้วย JavaScript โดยตรงครับ จะถูกลบออกเมื่อผู้ใช้ปิดแท็บ/เบราว์เซอร์ครับ

  • Local Storage:

    ไม่แนะนำสำหรับการเก็บ Access Token ที่มีความสำคัญสูง เพราะเสี่ยงต่อการถูกโจมตีแบบ XSS ครับ ถ้าถูกโจมตี ผู้โจมตีสามารถขโมย Token ไปได้ง่ายๆ

สำหรับ Refresh Token, HttpOnly Cookie มักเป็นตัวเลือกที่ดีที่สุดครับ สำหรับ Access Token อาจเก็บใน Memory หรือ HttpOnly Cookie ขึ้นอยู่กับสถาปัตยกรรมและข้อกำหนดด้านความปลอดภัยของแอปพลิเคชันครับ

Q4: การเพิกถอน (Revocation) Access Token ที่เป็น JWT ทำได้อย่างไร?

A4: โดยธรรมชาติแล้ว JWT ไม่มีกลไกการเพิกถอนในตัว เพราะมันเป็น Stateless ครับ อย่างไรก็ตาม เราสามารถใช้กลไกเพิ่มเติมเพื่อจำลองการเพิกถอนได้:

  • Short-lived Access Token + Refresh Token:

    กำหนดให้ Access Token มีอายุสั้นมากๆ (เช่น 5-15 นาที) หากต้องการเพิกถอน เพียงแค่เพิกถอน Refresh Token ครับ เมื่อ Access Token หมดอายุ ผู้ใช้จะไม่สามารถขอ Access Token ใหม่ได้อีกต่อไป

  • Blacklist/Revocation List:

    เมื่อต้องการเพิกถอน Access Token ทันที (เช่น ผู้ใช้ออกจากระบบ, รหัสผ่านถูกเปลี่ยน) สามารถเพิ่ม JWT ID (jti claim) ของ Token นั้นๆ ลงใน Blacklist ที่เก็บไว้ในฐานข้อมูลหรือ Cache (เช่น Redis) Resource Server จะตรวจสอบ Blacklist นี้ก่อนทุกครั้งที่ได้รับ JWT ครับ

  • Reference Tokens:

    แทนที่จะให้ JWT ที่มีข้อมูลเต็มรูปแบบ คุณอาจให้ Token ที่เป็นเพียง ID อ้างอิง (Reference Token) และเก็บข้อมูล Payload จริงไว้ที่ Authorization Server หรือ Token Introspection Endpoint ครับ เมื่อ Resource Server ได้รับ Reference Token ก็จะเรียกไปยัง Endpoint นั้นเพื่อขอข้อมูลและตรวจสอบ Token ครับ

Q5: OAuth 2.0 จำเป็นต้องใช้ JWT เสมอไปไหม?

A5: ไม่จำเป็นเสมอไปครับ OAuth 2.0 เป็นเฟรมเวิร์กที่ยืดหยุ่น โดยมาตรฐานไม่ได้บังคับว่า Access Token จะต้องเป็น JWT ครับ Access Token สามารถเป็นสตริงที่ไม่โปร่งใส (Opaque Token) ที่ Resource Server ต้องเรียก Authorization Server เพื่อตรวจสอบ (Token Introspection) หรือเป็นรูปแบบอื่นก็ได้ครับ

อย่างไรก็ตาม JWT เป็นรูปแบบที่ได้รับความนิยมอย่างมากในการนำมาใช้เป็น Access Token ในระบบ OAuth 2.0 และ OpenID Connect เพราะข้อดีเรื่อง Statelessness และ Self-contained ที่ช่วยเพิ่มประสิทธิภาพและ Scalability ให้กับระบบ API ครับ

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

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

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

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

หากคุณกำลังมองหาผู้เชี่ยวชาญด้านการพัฒนาหรือให้คำปรึกษาเกี่ยวกับระบบ Authentication และ Authorization หรือต้องการสร้าง 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