ข้ามไปยังเนื้อหา

Tokens, JWT & OAuth

API ส่วนใหญ่ทำ authenticate ด้วย bearer token: credential ที่ client แสดงในทุก request JWT เป็นรูปแบบ token ที่ได้รับความนิยม และ OAuth2 คือ protocol สำหรับการขอ token ในนามของ user

Authorization: Bearer <token>

“Bearer” แปลว่าใครถือ token ไว้ก็ใช้ได้ ดังนั้น token ต้องวิ่งผ่าน HTTPS เท่านั้น มีอายุสั้น และเพิกถอนได้

JSON Web Token มีสามส่วนที่เข้ารหัสแบบ base64url คั่นด้วยจุด: header.payload.signature ส่วน header ระบุ algorithm ส่วน payload เก็บ claims (เช่น sub, exp, aud, iss) และ signature ถูกคำนวณโดยผู้ออก (issuer) จากสองส่วนแรก

JavaScript

ใครก็ อ่าน payload ของ JWT ได้ เพราะไม่ได้เข้ารหัสไว้ ความเชื่อถือมาจากการ verify signature ด้วยกุญแจของ issuer เท่านั้น และการตรวจ exp (ยังไม่หมดอายุ), aud (ออกมาเพื่อ API ของคุณ) และ iss (มาจาก issuer ที่เชื่อถือได้) อย่าเชื่อ claims ที่คุณยังไม่ได้ verify เด็ดขาด

OAuth2 ทำให้ user มอบสิทธิ์การเข้าถึงแบบจำกัดให้แอปได้โดยไม่ต้องแชร์ password ส่วน flow ที่ใช้กันมากที่สุด:

sequenceDiagram
  participant U as User
  participant App as Client App
  participant AS as Authorization Server
  participant API as Resource API
  U->>App: use the app
  App->>AS: redirect to authorize (scopes)
  U->>AS: log in + consent
  AS-->>App: authorization code
  App->>AS: exchange code (+ secret) for tokens
  AS-->>App: access token (+ refresh token)
  App->>API: request + Bearer access token
  API-->>App: protected resource
OAuth2 authorization-code flow (OIDC เพิ่ม identity token เข้ามา)

Scope จำกัดว่า token ทำอะไรได้บ้าง (articles:read, articles:write) API ของคุณจะตรวจ scope ของ token ในระหว่างขั้นตอน authorization ส่วน OpenID Connect (OIDC) เพิ่มชั้นของตัวตน (id_token) ทับลงบน OAuth2 อีกที

Token Typeข้อดีข้อเสียเหมาะกับ
JWT (stateless)ไม่ต้อง query database ทุก requestrevoke ยาก ต้องรอ expireAPI ที่ scale สูง, microservice
Opaque Token (stateful)revoke ได้ทันทีต้อง lookup database ทุก requestSession ที่ต้องการ revoke บ่อย
API Keyง่าย, long-livedไม่มี expiry, revoke ยากServer-to-server, developer API
OAuth Access Tokendelegated auth, scope จำกัดsetup ซับซ้อนThird-party integration

เก็บ JWT ใน localStorage อาการ:

  • localStorage.setItem('token', jwt) ใน browser
  • XSS attack ขโมย token ได้
  • เก็บใน httpOnly cookie แทน — JavaScript อ่านไม่ได้

JWT ที่ไม่ Expire อาการ:

  • jwt.sign(payload, secret) โดยไม่ตั้ง expiresIn
  • token ที่ถูกขโมย valid ตลอดไป
  • ตั้ง expiresIn: '1h' และมี refresh token mechanism

💡 ตัวอย่างจากของจริง

GitHub API:

  • Personal Access Token (opaque) — revoke ได้ทันทีจาก settings
  • GitHub Apps ใช้ JWT สำหรับ installation token ที่ expire ใน 1 ชั่วโมง

Stripe API:

  • API Key สำหรับ server-to-server — อย่าใช้ใน client-side code
  • Restricted Key ที่จำกัด permission เฉพาะที่ต้องการ
JWT มีสามส่วนใดบ้าง?
ทำไมแค่อ่าน payload ของ JWT จึงยังไม่พอที่จะเชื่อถือ token นั้น?
OAuth2 scope ควบคุมอะไร?