Tokens, JWT & OAuth
API ส่วนใหญ่ทำ authenticate ด้วย bearer token: credential ที่ client แสดงในทุก request JWT เป็นรูปแบบ token ที่ได้รับความนิยม และ OAuth2 คือ protocol สำหรับการขอ token ในนามของ user
bearer token
หัวข้อที่มีชื่อว่า “bearer token”Authorization: Bearer <token>“Bearer” แปลว่าใครถือ token ไว้ก็ใช้ได้ ดังนั้น token ต้องวิ่งผ่าน HTTPS เท่านั้น มีอายุสั้น และเพิกถอนได้
JWT คืออะไร
หัวข้อที่มีชื่อว่า “JWT คืออะไร”JSON Web Token มีสามส่วนที่เข้ารหัสแบบ base64url คั่นด้วยจุด: header.payload.signature ส่วน header ระบุ algorithm ส่วน payload เก็บ claims (เช่น sub, exp, aud, iss) และ signature ถูกคำนวณโดยผู้ออก (issuer) จากสองส่วนแรก
ใครก็ อ่าน payload ของ JWT ได้ เพราะไม่ได้เข้ารหัสไว้ ความเชื่อถือมาจากการ verify signature ด้วยกุญแจของ issuer เท่านั้น และการตรวจ exp (ยังไม่หมดอายุ), aud (ออกมาเพื่อ API ของคุณ) และ iss (มาจาก issuer ที่เชื่อถือได้) อย่าเชื่อ claims ที่คุณยังไม่ได้ verify เด็ดขาด
OAuth2 authorization-code flow
หัวข้อที่มีชื่อว่า “OAuth2 authorization-code flow”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
Scope จำกัดว่า token ทำอะไรได้บ้าง (articles:read, articles:write) API ของคุณจะตรวจ scope ของ token ในระหว่างขั้นตอน authorization ส่วน OpenID Connect (OIDC) เพิ่มชั้นของตัวตน (id_token) ทับลงบน OAuth2 อีกที
| Token Type | ข้อดี | ข้อเสีย | เหมาะกับ |
|---|---|---|---|
| JWT (stateless) | ไม่ต้อง query database ทุก request | revoke ยาก ต้องรอ expire | API ที่ scale สูง, microservice |
| Opaque Token (stateful) | revoke ได้ทันที | ต้อง lookup database ทุก request | Session ที่ต้องการ revoke บ่อย |
| API Key | ง่าย, long-lived | ไม่มี expiry, revoke ยาก | Server-to-server, developer API |
| OAuth Access Token | delegated 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 เฉพาะที่ต้องการ