โทเค็นผู้ถือ (Bearer token) คืออะไร?
เรียนรู้ว่าโทเค็นผู้ถือคืออะไร ทำงานอย่างไรใน OAuth 2.0 และ JWT ต่างจาก access token อย่างไร พร้อมแนวปฏิบัติที่ดีที่สุด
เรียนรู้ว่าโทเค็นผู้ถือคืออะไร ทำงานอย่างไรใน OAuth 2.0 และ JWT ต่างจาก access token อย่างไร พร้อมแนวปฏิบัติที่ดีที่สุด
เบื้องหลังการล็อกอินแอปสมัยใหม่หรือการร้องขอ API เกือบทุกครั้ง จะมี “โทเค็นผู้ถือ” (bearer token) เป็นกลไกสำคัญ แม้จะไม่ทันสังเกตเห็น แต่ทุกครั้งที่เชื่อมต่อบริการ ล็อกอิน หรือดึงข้อมูลจากคลาวด์ โทเค็นชนิดนี้ทำงานเสมอ
คู่มือนี้จะพาไปรู้จักว่าโทเค็นผู้ถือคืออะไร สำคัญอย่างไร และควรจัดการอย่างไรให้ปลอดภัย
โทเค็นผู้ถือ คือข้อมูลบางอย่าง โดยมากเป็นสตริงตัวอักษร ใช้ยืนยันว่าผู้ที่ถือโทเค็นนี้มีสิทธิ์เข้าถึงทรัพยากร จุดสำคัญคือ ใคร "ถือ" โทเค็นนี้อยู่ ก็สามารถใช้งานได้เลย ไม่ต้องแสดงหลักฐานเพิ่มเติม
ให้จินตนาการถึงบัตรขึ้นเครื่องบิน เมื่อถือบัตรนี้ คุณผ่านด่านและขึ้นเครื่องได้เลย ไม่มีใครบอกให้โชว์บัตรประชาชนอีกถ้าบัตรขึ้นเครื่องยังใช้งานได้ โทเค็นผู้ถือก็เช่นกัน แอปของคุณจึง "ขึ้นเครื่อง" API ได้โดยไม่ต้องยืนยันตัวตนซ้ำทุกครั้ง
ตัวอย่างเช่น เมื่อล็อกอิน Spotify บนโทรศัพท์ คุณไม่ต้องกรอกรหัสผ่านใหม่ทุกครั้งที่เล่นเพลง แอปจะเก็บโทเค็นผู้ถือไว้เพื่อบอกเซิร์ฟเวอร์ Spotify ว่า “คำขอนี้มาจากผู้ใช้ที่ได้รับอนุญาต”
ลำดับการใช้งานโทเค็นผู้ถือมีดังนี้:
ผู้ใช้ล็อกอิน
สมมติคุณล็อกอินแอปธนาคารด้วยชื่อผู้ใช้และรหัสผ่าน
ผู้ออกโทเค็นยืนยันตัวตน
หลังจากตรวจสอบสำเร็จ เซิร์ฟเวอร์ยืนยันตัวตนจะส่งโทเค็นผู้ถือกลับมา อาจหน้าตาแบบนี้:
แอปนำโทเค็นไปใช้
ทุกครั้งที่คุณแตะ “เช็คยอดเงิน” หรือ “โอนเงิน” แอปจะใส่โทเค็นนี้ไปใน HTTP request:
API ตรวจสอบความถูกต้อง
เซิร์ฟเวอร์จะตรวจว่าโทเค็นยังใช้ได้ ไม่หมดอายุ และมีสิทธิ์ถูกต้อง (เช่น read:balance หรือ write:transfer)
อนุมัติการเข้าถึง
ถ้าทุกอย่างผ่าน เซิร์ฟเวอร์จะส่งข้อมูลที่ร้องขอกลับมา
โมเดลนี้ถูกใช้แพร่หลายในบริการเช่น GitHub APIs นักพัฒนาใช้โทเค็นผู้ถือแทนใส่รหัสผ่านซ้ำบ่อยๆ
โทเค็นผู้ถือกลายเป็นที่นิยม เพราะแก้ไขปัญหาด้านความปลอดภัยบนเว็บได้ดี แตกต่างจาก session ฝั่งเซิร์ฟเวอร์ ที่ต้องจำสถานะของผู้ใช้แต่ละคน แต่โทเค็นผู้ถือฝังข้อมูลพอให้เซิร์ฟเวอร์ตรวจสอบได้ด้วยตัวเอง
เช่น ในสถาปัตยกรรม microservices ที่บริการย่อยจำนวนมากคุยกัน การเก็บ session ตรงกลางจะยุ่งยากมาก ใช้โทเค็นผู้ถือแต่ละบริการตรวจสอบได้เอง เบาเครื่องและขยายง่าย
ตัวอย่างชัดเจน: API ของ Slack พึ่งพาโทเค็นผู้ถืออย่างมาก หากสร้าง Slack bot จะได้โทเค็นมาให้เรียก endpoint ต่างๆ ได้โดยไม่ต้องเก็บ session ให้ผู้ใช้ทุกคน
โทเค็นผู้ถือจำนวนมากจะสร้างแบบ JWT (JSON Web Token) โดยฝังข้อมูลผู้ใช้และสิทธิ์ต่างๆ ไว้
ลองถอดรหัส JWT ตัวอย่าง:
ความหมายคือ:
sub: รหัสประจำตัวผู้ใช้name: ชื่อผู้ใช้iat: เวลาที่ออกโทเค็น (issued at)exp: หมดอายุเมื่อไหร่scope: สิทธิ์ใช้งาน เช่น ตัวอย่างนี้ให้ทั้งอ่านและเขียนข้อความในความเป็นจริง ถ้าโทเค็นของ Jane มี scope แค่ read:messages แอปจะอ่านข้อความได้ แต่จะเขียนแทนเธอไม่ได้
ง่ายที่จะสับสนระหว่าง โทเค็นผู้ถือ กับ access token เพราะศัพท์นี้มักมากับคู่กัน ทั้งที่จริงแล้วมีความเกี่ยวข้องแต่ไม่เหมือนกันทุกอย่าง
Access token คือข้อมูลที่บ่งชี้ว่าผู้ใช้ได้รับอนุญาตให้เข้าถึงทรัพยากร ประกอบด้วยเช่น:
เปรียบเสมือน “ใบอนุญาต” ที่ผู้อำนวยการโรงเรียนลงนาม มอบให้ครู (API) ว่าเด็กคนนี้ไปทัศนศึกษาได้ (เข้าถึงทรัพยากร)
เช่นเวลาใช้คลาวด์สตอเรจ ระบบจะออก access token พร้อม scope read:files หมายความว่า ผู้ใช้จะอ่านไฟล์ได้แต่ลบไม่ได้
Bearer token คือรูปแบบหนึ่งของ access token โดยคำว่า bearer อธิบาย รูปแบบการใช้งาน: ใครนำโทเค็นนี้ไปแสดงก็เข้าถึงข้อมูลได้ ไม่ต้องยืนยันตัวตนเพิ่มเติม
สรุปสั้น ๆ:
ยังมีโทเค็นประเภทอื่นเช่น holder-of-key token ที่ต้องใช้กุญแจเข้ารหัสร่วมด้วย เวลานำโทเค็นไปใช้ Bearer token ไม่ต้องพิสูจน์เพิ่ม จึงง่ายแต่ถ้าโดนขโมยก็เสี่ยงกว่า
<token> headerดังนั้นคำว่า “access token” ในคู่มือ OAuth โดยมากจะหมายถึง bearer token เว้นแต่จะระบุเป็นพิเศษ
เพื่อให้เห็นภาพ ลองดูว่า bearer token ต่างกับโทเค็นชนิดอื่นอย่างไร:
Bearer token กับ access token ไม่ใช่สิ่งตรงข้ามกัน — แต่เกี่ยวข้องกัน:
การตรวจสอบความถูกต้องของ bearer token คือแนวป้องกันสุดท้ายที่ขวางการเข้าถึงโดยไม่ได้รับอนุญาต ถ้าเป็น JWT จะตรวจได้ในเครื่อง รวดเร็ว ไม่ต้องติดต่อผู้ออกโทเค็นเสมอ
ใช้รายการนี้ประกอบเมื่อเชื่อมต่อ API gateway หรือ middleware
ลายเซ็น (Signature)
ตรวจสอบลายเซ็นด้วยอัลกอริทึมใน header (เช่น RS256) ดึง JWKS endpoint ของผู้ออกโทเค็น เลือก key ให้ตรงกับ kid จากนั้น cache ไว้
Issuer (iss)
เปรียบเทียบ iss ในโทเค็นกับ URL ที่ไว้วางใจ สำคัญที่ schema และต้องตรงเป๊ะ
Audience (aud)
ตรวจสอบว่าโทเค็นออกให้ API ของเรา เช่น https://api.example.com หรือสตริงที่กำหนดไว้
Expired (exp) กับ Not-Before (nbf)
ปฏิเสธโทเค็นที่หมดอายุ เคารพ nbf เพื่อป้องกันการใช้งานก่อนเวลา ปรับ clock skew 30-60 วินาที
ออกเมื่อ (iat)
ใช้สำหรับ debug หรือกรณีที่ต้องปฏิเสธโทเค็นเก่า
ประเภทโทเค็น
ยืนยันว่าเป็น access token บางเจ้าใส่ typ: "at+jwt" หรือคล้ายกัน อย่าใช้ ID token กับ API
Scope / สิทธิ์
อ่าน scope หรือคลามเฉพาะผู้ให้บริการ (permission, roles ฯลฯ) บังคับ least privilege ในแต่ละ endpoint
Subject (sub)
เป็นรหัสผู้ใช้หรือ client ที่คงที่ ใช้โยงกับทรัพยากรหรือบันทึก log
ป้องกัน replay/yank (ไม่จำเป็นแต่แนะนำ)
โดยเฉพาะ endpoint สำคัญ ควรตรวจสอบรายชื่อ jti blacklist หรือ session เพื่อป้องกันหลัง logout/นำโทเค็นไปใช้โดยมิชอบ
เพราะ bearer token คือ “ใครถือก็ใช้ได้” จึงต้องปกติเหมือนกุญแจบ้าน ถ้าใครขโมยไปก็เปิดประตูได้จนกว่าจะเปลี่ยนกุญแจใหม่
ความเสี่ยงที่พบบ่อยได้แก่:
โลกจริงมีกรณีที่ dev เผลอโพสต์ bearer token ลงใน GitHub สาธารณะ ทำให้แฮกเกอร์สแกนหาโทเค็นเหล่านี้ และใช้เข้าถึงระบบโดยไม่ได้รับอนุญาตทันที
เพื่อใช้งาน bearer token อย่างปลอดภัย ควรปฏิบัติดังนี้:
ใช้ HTTPS เสมอ
หากส่งโทเค็นผ่าน HTTP ปกติที่ร้านกาแฟ ใครดักจับเน็ต ก็นำโทเค็นไปเข้าระบบแทนคุณได้
ใช้งานโทเค็นอายุสั้น
ส่วนใหญ่โทเค็นจะหมดอายุในหนึ่งชั่วโมง เช่น OAuth ของ Google จะใช้งานได้ราวหนึ่งชั่วโมงก่อนต้อง refresh
จัดการ refresh token อย่างระมัดระวัง
Refresh token เอาไว้ขอโทเค็นใหม่โดยผู้ใช้ไม่ต้องล็อกอินอีก แต่ต้องเก็บแบบปลอดภัย (เช่น ฐานข้อมูลฝั่งเซิร์ฟเวอร์) ไม่ควรเก็บฝั่ง client
ให้น้อยแต่พอดี (least privilege)
ถ้าแอปอ่านปฏิทินอย่างเดียว ก็ขอแค่ read:calendar ไม่ขอ write:calendar เพื่อจำกัดความเสียหายหากโทเค็นถูกขโมย
เพิกถอนโทเค็นเมื่อจำเป็น
SaaS หลายรายให้ผู้ใช้ดู session ปัจจุบัน หรือ revoke ได้ เช่น GitHub ให้ลบ personal access token ทันทีที่ต้องการ
ตรวจสอบการใช้งาน
บันทึกการใช้โทเค็น จะช่วยสังเกตสิ่งผิดปกติ เช่น โทเค็นเดียวถูกใช้จาก London กับ New York ในเวลาสั้น ๆ เป็นสัญญาณอันตราย
เปรียบเทียบ bearer token กับแนวทางอื่นที่นิยม:
Cookies & Sessions
เว็บไซต์ดั้งเดิมจะเก็บ session ฝั่งเซิร์ฟเวอร์ แล้วเชื่อมกับ cookie ฝั่ง client วิธีนี้เหมาะกับเว็บเบราว์เซอร์แต่ไม่ดีสำหรับ API หรือแอปมือถือ เช่น Facebook เวอร์ชัน desktop ใช้ cookie แต่ API มือถือใช้โทเค็น
API Key
API key เป็นสตริงคงที่ ระบุแอปที่เรียก API ไม่ได้บอกว่าผู้ใช้คือใคร ตัวอย่างเช่นแอปพยากรณ์อากาศใช้ API key ดึงข้อมูล แต่ server จะไม่ทราบว่า user คนไหน Bearer token สามารถฝังข้อมูลผู้ใช้ได้จึงยืดหยุ่นกว่า
Mutual TLS (mTLS)
ระบบความปลอดภัยสูงนำ certificate ฝั่ง client และ server ตรวจสอบกันเอง ปลอดภัยกว่าแต่ตั้งค่ายาก API ของ SaaS ส่วนมากใช้ bearer token เพื่อสมดุลย์ระหว่างความปลอดภัยและใช้งานง่าย