Authentication & Authorization — ใครเป็นใคร ทำอะไรได้
Sessions · JWT · OAuth 2.0 · OpenID Connect · RBAC · ABAC · ▶ ในคลิป 1:23:41 – 1:55:51
สองคำที่หน้าตาคล้ายแต่คนละเรื่อง: Authentication (AuthN) = พิสูจน์ว่า "คุณคือใคร" ส่วน Authorization (AuthZ) = ตัดสินว่า "คุณทำสิ่งนี้ได้ไหม" — เปรียบกับสนามบิน: ด่านตรวจพาสปอร์ตคือ authentication ส่วนตั๋ว boarding pass ที่บอกว่าคุณขึ้นเครื่องลำไหน ที่นั่ง class อะไร คือ authorization · ระบบตอบ 401 เมื่อ AuthN ล้มเหลว และ 403 เมื่อ AuthZ ล้มเหลว
7.1 ปัญหาตั้งต้น: HTTP จำใครไม่ได้
HTTP เป็น stateless — login สำเร็จแล้ว request ถัดไปเซิร์ฟเวอร์ก็ไม่รู้ว่าเป็นคนเดิม เราจึงต้องมี "หลักฐาน" แนบไปกับทุก request มีสองสำนักใหญ่:
7.2 สำนักที่หนึ่ง: Session + Cookie (Stateful)
หลัง login เซิร์ฟเวอร์สร้าง session record เก็บฝั่งตัวเอง (ใน Redis/DB) แล้วส่งแค่ session ID ใส่ cookie ให้เบราว์เซอร์ — ทุก request ถัดไป เบราว์เซอร์แนบ cookie อัตโนมัติ เซิร์ฟเวอร์เอา ID ไปเปิดดูว่าเป็นใคร
- ข้อดี — เพิกถอนได้ทันที (ลบ session ทิ้ง = logout ทุกอุปกรณ์), ข้อมูล session อัปเดตสดเสมอ
- ข้อเสีย — ทุก request ต้องเปิด lookup หนึ่งครั้ง และใน scale-out ต้องมี shared session store ให้ทุกเครื่องอ่านร่วมกัน (บทที่ 3)
7.3 สำนักที่สอง: JWT (Stateless Token)
JWT (JSON Web Token) พลิกแนวคิด: แทนที่จะเก็บข้อมูลฝั่งเซิร์ฟเวอร์ ก็ ยัดข้อมูลลงใน token แล้วเซ็นลายเซ็นดิจิทัลกำกับ เซิร์ฟเวอร์แค่ตรวจลายเซ็นก็เชื่อเนื้อหาข้างในได้เลย — ไม่ต้องเปิด DB
จุดแลกเปลี่ยนที่ต้องท่องให้ขึ้นใจ: JWT เพิกถอนกลางอากาศไม่ได้ — token ที่เซ็นแล้วจะใช้ได้จนกว่าจะหมดอายุ (exp) ต่อให้ผู้ใช้ถูกแบนไปแล้วก็ตาม ทางแก้มาตรฐานคือคู่ token:
- Access Token — อายุสั้นมาก (5–15 นาที) ใช้แนบทุก request ใน header
Authorization: Bearer <token> - Refresh Token — อายุยาว (วัน/สัปดาห์) เก็บอย่างปลอดภัย ใช้ ขอ access token ใหม่ เมื่อตัวเก่าหมดอายุ — และฝั่งเซิร์ฟเวอร์เพิกถอน refresh token ได้ (จุดนี้ stateful) ทำให้แบนผู้ใช้มีผลภายในไม่กี่นาที
| มิติ | Session + Cookie | JWT |
|---|---|---|
| เก็บ state ที่ | เซิร์ฟเวอร์ (Redis/DB) | ตัว token เอง (client ถือ) |
| ตรวจสอบ | lookup ทุก request | ตรวจลายเซ็น ไม่แตะ DB |
| เพิกถอน | ทันที | ต้องรอหมดอายุ / ใช้คู่ refresh token |
| Scale-out | ต้องมี shared store | เครื่องไหนก็ตรวจได้เอง — เหมาะ microservices |
| เหมาะกับ | เว็บแอปดั้งเดิม, ระบบที่ความปลอดภัยนำ | API, mobile, ระบบกระจายหลาย service |
7.4 OAuth 2.0 — มอบสิทธิ์โดยไม่มอบรหัสผ่าน
โจทย์ของ OAuth: แอป A อยากเข้าถึงข้อมูลของคุณในบริการ B (เช่น แอปตัดต่อรูปขอเข้าถึง Google Photos) — วิธีโบราณคือเอารหัสผ่าน Google ไปกรอกในแอป ซึ่งอันตรายสุดขีด OAuth 2.0 แก้ด้วยการให้ B ออก token ที่จำกัดขอบเขต (scope) และเพิกถอนได้ ให้ A แทน — ผู้เล่นมี 4 ฝ่าย:
- Resource Owner — ผู้ใช้ (เจ้าของข้อมูล)
- Client — แอปที่ขอสิทธิ์ (แอปตัดต่อรูป)
- Authorization Server — ผู้ออก token (หน้า login ของ Google)
- Resource Server — API ที่ถือข้อมูล (Google Photos API)
สองรายละเอียดที่ใช้จริง: scope จำกัดว่า token ทำอะไรได้ (photos.read อ่านได้แต่ลบไม่ได้) และ PKCE — ส่วนขยายภาคบังคับสำหรับ mobile/SPA ที่เก็บ client secret ไม่ได้ ใช้คู่ challenge/verifier กันคนดัก authorization code ไปแลก token แทนเรา
7.5 OpenID Connect (OIDC) — ชั้นตัวตนบน OAuth
OAuth 2.0 ออกแบบมาเพื่อ "มอบสิทธิ์เข้าถึง" ไม่ใช่ "ยืนยันตัวตน" — ปุ่ม "Sign in with Google" ที่เราเห็นทุกวันคือ OIDC: ชั้นบาง ๆ บน OAuth ที่เพิ่ม ID Token (เป็น JWT) ซึ่งบรรจุข้อมูลตัวตนที่ยืนยันแล้ว (ชื่อ, อีเมล, รูป) — จำง่าย ๆ: OAuth = สิทธิ์ (authorization), OIDC = ตัวตน (authentication) และแอปจำนวนมากใช้ทั้งคู่ใน flow เดียวกัน
7.6 Access Control — RBAC vs ABAC
รู้ตัวตนแล้ว ขั้นต่อไปคือตัดสินใจว่า "ทำได้ไหม" สองโมเดลหลัก:
| RBAC (Role-Based) | ABAC (Attribute-Based) | |
|---|---|---|
| หลักการ | ผูกสิทธิ์กับ "บทบาท" แล้วแจกบทบาทให้คน | เขียนกฎจาก "คุณลักษณะ" ของผู้ใช้ + ทรัพยากร + บริบท |
| ตัวอย่างกฎ | role = editor → แก้บทความได้ทุกชิ้น | แก้ได้ถ้า user.dept == doc.dept และ time ∈ เวลางาน และ doc.status != locked |
| ความละเอียด | หยาบ — สิทธิ์เหมาเข่งตาม role | ละเอียดระดับเงื่อนไขรายชิ้น |
| ดูแลรักษา | ง่าย เข้าใจไว ตรวจสอบ (audit) ง่าย | กฎซับซ้อน debug ยากกว่า — แต่ยืดหยุ่นสุด |
| เหมาะกับ | องค์กรโครงสร้างชัด (admin/editor/viewer) | ระบบ multi-tenant, ข้อกำหนดกำกับดูแลซับซ้อน |
ของจริงมักเป็น ลูกผสม: ใช้ RBAC เป็นโครงหลัก (เข้าใจง่าย) แล้วเสริมเงื่อนไข attribute เฉพาะจุดที่ต้องละเอียด เช่น "editor แก้บทความได้ เฉพาะของทีมตัวเอง"
✅ สรุปบทที่ 7 — AuthN = คุณคือใคร (401) · AuthZ = ทำได้ไหม (403) · Session = เพิกถอนง่าย แต่ต้อง lookup · JWT = ตรวจเองได้ไม่แตะ DB แต่เพิกถอนยาก → ใช้ access สั้น + refresh ยาว · OAuth = มอบสิทธิ์ข้ามแอปโดยไม่มอบรหัสผ่าน · OIDC = ชั้นยืนยันตัวตนบน OAuth · RBAC เริ่มง่าย เสริม ABAC เมื่อต้องละเอียด