~/VibeHandbook
PDF ฟรี

บท 18 · 04

Authentication vs Authorization: เอนด์พอยต์ที่ใครก็เรียกได้

สองคำนี้ฟังดูคล้ายกัน และความแตกต่างระหว่างมันคือจุดที่การเจาะระบบจริง ๆ มักเกิดขึ้น

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

AI ทำ authentication ได้ดีพอสมควร เพราะไลบรารีจัดการส่วนใหญ่ให้อยู่แล้ว Authorization ต่างหากที่มันมักล้มเหลวเป็นประจำ เพราะ authorization ขึ้นอยู่กับกฎเฉพาะของแอปคุณ ซึ่ง AI ไม่รู้จัก นี่คือหายนะในตำราเรียน:

// VULNERABLE: checks you're logged in, but not WHO you are
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  res.json(db.getAllUsers()); // any logged-in user can hit this
});

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

// SAFE: confirms this user is actually an admin
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  if (!req.user.isAdmin) return res.status(403).send("Forbidden");
  res.json(db.getAllUsers());
});

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

  request ──▶ ┌──────────────────┐  ──▶ ┌──────────────────┐  ──▶  action
              │ AUTHENTICATION   │      │ AUTHORIZATION     │       runs
              │ "logged in?"     │      │ "may THIS user    │
              │                  │      │  do THIS action?" │
              └──────────────────┘      └──────────────────┘
                  ✓ most apps              ✗ often missing
                    build this               → the breach

  EXAMPLE — /admin/export-all-users
     logged-in user  ──▶ [auth ✓] ──▶ [ no authz check ] ──▶ ALL users dumped
     logged-in user  ──▶ [auth ✓] ──▶ [ isAdmin? → 403  ] ──▶ blocked  ✓

กับดักเดียวกันปรากฏในรูปแบบย่อ ๆ ได้ทุกที่ เช่น เอนด์พอยต์ที่คืนค่าออเดอร์หมายเลข #1234 โดยไม่ตรวจสอบว่าออเดอร์นั้นเป็นของผู้ใช้ที่ร้องขอหรือไม่ ใครก็สามารถเปลี่ยนหมายเลขใน แล้วอ่านออเดอร์ของคนอื่นได้ กฎที่ไม่หรูหราแต่เด็ดขาดคือ: ตรวจสอบสิทธิ์บนทุกเอนด์พอยต์ที่แตะข้อมูล และอย่าไว้ใจ ID ที่มาจากไคลเอนต์ อย่าคิดว่า URL ที่ซ่อนอยู่จะปลอดภัยเพราะมันถูกซ่อนไว้ — "ไม่มีใครรู้ว่าสิ่งนี้มีอยู่" ไม่ใช่มาตรการรักษาความปลอดภัย

อยากได้แบบออฟไลน์?

ดาวน์โหลดหนังสือทั้งเล่มเป็น PDF หรือ EPUB — ฟรี