สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video
ในหัวข้อนี้ เราจะพาทุกคนมารู้จักกับมาตรฐานการยืนยันสิทธิ์ที่ใช้งานกันอย่างแพร่หลายในอุตสาหกรรม Software “OAuth” กันว่ามันคืออะไร มีหลักการประมาณไหน และ application แต่ละแบบควรใช้งานกับ OAuth แบบไหนบ้าง มาเรียนรู้ผ่านหัวข้อนี้กันครับ
แนะนำ Authentication และ Authorization
ก่อนจะรู้จักกับ OAuth เราต้องรู้จักกับ Authentication และ Authorization กันเสียก่อน 2 ตัวนี้เหมือนจะคล้ายๆกัน แต่มีความหมายต่างกันสิ้นเชิง
Authentication (การรับรองความถูกต้อง) คือกระบวนการในการยืนยันตัวตนของผู้ใช้งานหรือกระบวนการก่อนที่จะอนุญาตให้เข้าถึงระบบหรือ Resource ที่ได้รับการป้องกัน นั่นคือ กระบวนการรับรองความถูกต้อง เป็นการตรวจสอบว่าผู้ใช้งานคนนั้นเป็นคนที่อ้างว่าเป็นจริงหรือไม่ โดยระบบจะขอข้อมูลที่เป็นความลับจากผู้ใช้งาน เช่น รหัสผ่าน คำตอบจากคำถามรักษาความปลอดภัย ข้อมูล Biographic หรือรหัสผ่านชั่วคราว เพื่อใช้ในการพิสูจน์ตัวตน
Authorization (การอนุญาต) หลังจากที่ผู้ใช้งานผ่านการรับรองความถูกต้อง (Authentication) มาแล้ว ขั้นตอนต่อไปคือการอนุญาต ซึ่งเป็นกระบวนการในการกำหนดสิทธิ์ให้กับผู้ใช้งานที่ผ่านการรับรองความถูกต้องแล้วว่าสามารถเข้าถึง Resource หรือข้อมูลใดได้บ้าง การอนุญาตจะควบคุมว่าผู้ใช้งานมีสิทธิ์ในการดำเนินการอะไรกับ Resource นั้นๆได้บ้าง เช่น อ่าน เขียน แก้ไข หรือลบ เป็นต้น
โดย สิ่งที่เรียกว่า OAuth นั้นเป็นมาตรฐานสำหรับการอนุญาต (Authorization) มากกว่าการรับรองความถูกต้อง (Authentication) หากเปรียบเทียบได้กับ Authentication และ Authorization
- เวลาที่เราเข้าสู่ขั้นตอน Authentication เราจะทำการใส่ credential ที่ทำการยืนยันตัวตนกับระบบนั้นเข้าไป (เช่น email, password)
- หลังจาก email, password ผ่าน เราก็จะได้ key ที่เป็นตัวแทนของข้อมูลของเรากลับมา
- และหลังจากนั้น ทุกครั้งที่เราจะขอข้อมูลอะไรก็ตาม เราก็จะส่ง key ตัวนั้นแนบคู่ไป เพื่อเป็นการยืนยันว่าเราผ่านการยืนยันตัวตนมาเรียบร้อยแล้ว
และจุดนี้แหละที่ OAuth จะมามีบทบาทกับเรื่องนี้ เรามาลองทำความรู้จัก Oauth กันว่าคืออะไร
Oauth คืออะไร
OAuth (Open Authorization) เป็น protocal standard ที่ใช้สำหรับการอนุญาตให้ application สามารถเข้าถึงข้อมูลหรือ Resource ของผู้ใช้จาก application หรือบริการอื่น โดยไม่จำเป็นต้องแชร์ข้อมูลรับรองความถูกต้องที่เป็นความลับ เช่น รหัสผ่าน
โดย OAuth จะเน้นไปที่การอนุญาต (Authorization) มากกว่าการรับรองความถูกต้อง (Authentication) กล่าวคือ OAuth ไม่ได้เป็นกระบวนการในการยืนยันตัวตนของผู้ใช้โดยตรง แต่เป็นการอนุญาตให้ application สามารถเข้าถึงข้อมูลหรือ Resource ของผู้ใช้จาก application หรือบริการอื่นได้
โดยหลักการของ OAuth เมื่อใช้งานร่วมกันกับ Authorization คือ
- เริ่มต้น application จะส่งคำขออนุญาตให้ผู้ใช้เพื่อเข้าถึงข้อมูลหรือ Resource บางอย่างของผู้ใช้จากบริการหรือ application (เปิด application ขึ้นมาแล้วเจอว่าจำเป็นต้อง login) ไปยัง Authentication Server (Server สำหรับการยืนยันตัวตน)
- ผู้ใช้จะได้รับแจ้งรายละเอียดของสิทธิ์การเข้าถึงที่ application ต้องการ (User Grants Access) และหากผู้ใช้ยอมรับ ผู้ใช้จะอนุญาตให้ application เข้าถึงข้อมูลหรือ Resource ที่ส่ง request เข้ามาได้
- หลังจากผู้ใช้อนุญาตแล้ว application จะได้รับ Access Token ซึ่งเป็น string ข้อความที่ใช้ในการ confirm ว่า application ได้รับอนุญาตจากผู้ใช้แล้วเรียบร้อย
- Application จะใช้ Access Token ในการเข้าถึงข้อมูลหรือ Resource ของผู้ใช้จากบริการหรือ Application อื่นตามสิทธิ์ที่ได้รับอนุญาต (เราจะเรียกเจ้าของข้อมูลที่ปกป้องการเข้าถึงว่า Resource Server) โดยไม่จำเป็นต้องแชร์ข้อมูลรับรองความถูกต้องที่เป็นความลับ เช่น รหัสผ่าน ได้ (คุยผ่านตัวแทนอย่าง Access Token แทน)
- Access Token มีอายุการใช้งานจำกัด เมื่อหมดอายุแล้ว application จะต้องขอ Access Token ใหม่จากผู้ใช้อีกครั้ง
อย่างที่เห็น OAuth ช่วยให้ application สามารถเข้าถึงข้อมูลหรือ Resource ของผู้ใช้จากบริการหรือ application อื่นได้อย่างปลอดภัย โดยไม่ต้องแชร์ข้อมูลที่เป็นความลับ เช่น รหัสผ่าน ให้กับบริการหรือ application อื่นๆได้ ด้วยข้อดีนี้ส่งผลทำให้ OAuth เป็นมาตรฐานเปิดที่ใช้งานได้กับ platform ต่างๆ ทั้งเว็บ mobile และ desktop application รวมถึงส่งผลทำให้ Third Party Service หลายเจ้า สนับสนุนการใช้ OAuth สำหรับการยืนยันตัวตน เช่น Google, Facebook, Twitter ทำให้นักพัฒนาสามารถเชื่อมต่อ application กับบริการเหล่านี้ได้อย่างง่ายดาย โดยไม่จำเป็นต้องเก็บ credential เหล่านั้นเอาไว้ในระบบเราเองได้
Bearer Authentication ≠ OAuth
ทีนี้หลายคนก็จะเข้าใจว่า อ่อ เวลาที่เราทำเว็บไซต์และเราก็มี endpoint อย่าง /login
และได้ access token มาเก็บไว้ใน Cookie หรือส่งไปใน Bearer Token แปลว่าเราก็ implement OAuth ใช่ไหม ?
คำตอบก็คือ “ไม่นะครับ” เหตุผลเพราะว่า “เราเก็บของชิ้นนั้นไว้ที่เดียวกัน”
ตัว OAuth เป็นมาตรฐานสำหรับการอนุญาตให้ application หนึ่งสามารถเข้าถึงข้อมูลหรือ Resource ของผู้ใช้จากบริการหรือ application โดย “ไม่จำเป็นต้องแชร์ข้อมูลรับรองความถูกต้อง” จากเคสนี้ หากเราทำการเก็บ credential (สำหรับการยืนยันตัวตนของผู้ใช้) และ resource (ข้อมูลที่ผู้ใช้สามารถเข้าถึงได้) ไว้ที่เดียวกัน จะถือว่าเรายังคง “เก็บข้อมูลรับรองความถูกต้อง” เอาไว้ทีเดียวกับ resource ของเรานั่นเอง (ซึ่งก็จะไม่เป็นไปตามมาตรฐานของ OAuth แต่จะเป็นเพียง Bearer Token ที่เป็นการใช้ Access Token สำหรับการยืนยันตัวตนแค่นั้น (แต่ ทังนี้ Bearer Token ก็เป็นรูปแบบหนึ่งของ Access Token ที่ใช้ในกระบวนการ OAuth เพื่อพิสูจน์ว่าผู้ถือ Token นั้นได้รับอนุญาตให้เข้าถึง Resource หรือข้อมูลแล้วเช่นเดียวกัน)
โดย หากเราต้องการใช้ case นี้ของเราเป็นการ implement ตาม OAuth เราจะต้องมีองค์ประกอบต่อไปนี้เพิ่มเข้าไป
- Resource Server (ผู้ให้บริการ) ซึ่งเป็นเจ้าของข้อมูลหรือ Resource ของผู้ใช้
- Client Application ที่ต้องการเข้าถึงข้อมูลหรือ Resource ของผู้ใช้จากผู้ให้บริการ
- Authorization Server (เซิร์ฟเวอร์รับรองความถูกต้อง) ที่ทำหน้าที่ในการอนุญาตให้ application เข้าถึงข้อมูลหรือ Resource ของผู้ใช้
และจะต้องปรับขั้นตอนเป็น
- Client Application จะส่งคำขออนุญาตไปยัง Authorization Server
- Authorization Server จะแสดงหน้าจอให้ผู้ใช้อนุญาตหรือปฏิเสธการเข้าถึงข้อมูลหรือ Resource
- หากผู้ใช้อนุญาต Authorization Server จะออก Access Token ให้กับ application
- และสุดท้าย application ก็จะใช้ Access Token ในการเข้าถึงข้อมูลหรือ Resource ของผู้ใช้จากผู้ให้บริการได้
สังเกตนะครับว่า มันคือการ นำ Server สำหรับการยืนยันตน แยกส่วนออกมา ออกจาก ส่วนของข้อมูล Resource Server ดังนั้น มาตรฐาน OAuth จะวัดจากวิธีการเก็บ Credential ของเราไว้ด้วยว่า เราเก็บไว้ที่ไหนและแบบใด ซึ่งถึงแม้ว่า OAuth จะส่งผลทำให้หลายขั้นตอนดูซับซ้อนขึ้น (จริงๆก็ไม่มากหรอก) แต่จะช่วยเพิ่มความปลอดภัยและความเป็นส่วนตัวให้กับผู้ใช้ โดยไม่ต้องแชร์ข้อมูลรับรองความถูกต้องที่เป็นความลับกับ Client Application (โดยเฉพาะถ้าเป็น Third Party App) ได้ แต่ยังคงสามารถรับรองความถูกต้องของข้อมูลผู้ใช้ได้เช่นเดิม
แต่ ถึงแม้ว่าการ implement OAuth นั้นจะซับซ้อนและดูกินเวลาก็ตาม ในทางปฎิบัติจริงๆ สำหรับการทำงาน ส่วนใหญ่ Third Party service ที่เราใช้บริการ (ไม่ว่าจะเป็น Social Sign in อย่าง Google, Facebook, X) ก็ทำการ implement OAuth ขึ้นมาแล้วเรียบร้อย รวมถึงมี Authentication Service (อย่าง Auth0) ที่ช่วยทำให้นักพัฒนาอย่างเราๆ สามารถเพิ่มการ Authentication มาตรฐาน OAuth เข้าไปเองได้ โดยไม่จำเป็นต้อง implement OAuth ตั้งแต่ต้นออกมาได้เช่นกัน เราก็จะสามารถได้มาตรฐานความปลอดภัยเดียวกับ OAuth ออกมาได้ โดยไม่จำเป็นต้องลงทุนกับเวลาจำนวนมากไปกับการสร้าง OAuth server ได้
Oauth 1.0 vs Oauth 2.0
Ref: https://medium.com/@greekykhs/whats-the-difference-oauth-1-0-and-oauth-2-0-9f1d22e06963
แน่นอน OAuth ไม่ได้พึ่งกำเนิดมาช่วงไม่กี่ปีนี้ แต่ OAuth นั้น ถือกำเนิดมากว่า 10 ปีแล้ว (ตั้งแต่ปี 2010) ในปัจจุบันนั้น เรามีมาตรฐาน OAuth อยู่ทั้งหมด 2 Version ใหญ่ๆด้วยกัน คือ
- OAuth 1.0 เป็น version แรกของมาตรฐาน OAuth ที่ออกมาในปี 2010 มีจุดประสงค์หลักเพื่อให้ application สามารถเข้าถึงข้อมูลของผู้ใช้จากบริการออนไลน์อื่นๆได้อย่างปลอดภัย โดยไม่ต้องแชร์ข้อมูลรับรองความถูกต้องที่เป็นความลับ เช่น รหัสผ่าน ได้
จุดเด่นของ OAuth 1.0 คือ
- ใช้กระบวนการที่ซับซ้อน ประกอบด้วยหลายขั้นตอนและการแลกเปลี่ยน Request Token (Request Token เป็น token ชั่วคราวที่ใช้ในการขออนุญาตจากผู้ใช้เพื่อเข้าถึงข้อมูลหรือ Resource ของผู้ใช้) และ Access Token (Access Token เป็น token ที่ application ได้รับหลังจากผู้ใช้อนุญาตการเข้าถึงข้อมูลหรือ Resource แล้ว)
- ต้องใช้ Cryptographic Signature เพื่อรักษาความปลอดภัยของข้อมูลที่ส่งผ่านในแต่ละขั้นตอน
- Cryptographic Signature เป็นกลไกในการรักษาความปลอดภัยของ OAuth 1.0 โดยใช้ในการยืนยันความถูกต้องและความสมบูรณ์ของคำขอระหว่าง application และผู้ให้บริการ โดย application จะใช้ Consumer Secret (ถูกออกโดย Service Provider เป็นเหมือน Secret key ของ Service) และ Token Secret (ออกโดย Service Provider พร้อมกับ Access Token) ในการสร้าง Cryptographic Signature จาก Signature Base String และ application ก็จะแนบ Cryptographic Signature ไปพร้อมกับ request ต่างๆตอนมีการเรียกใช้ (และจะต้อง generate ทุก request เสมอด้วย)
- เหมาะสำหรับการเข้าถึงข้อมูลแบบ Non-interactive (ไม่มีการตอบโต้) เช่น การเข้าถึงข้อมูลผ่าน API
2. OAuth 2.0 เป็น version ล่าสุดของมาตรฐาน OAuth ที่ออกมาในปี 2012 ได้รับการปรับปรุงให้มีความง่ายและยืดหยุ่นมากขึ้น เพื่อรองรับการใช้งานกับ application ประเภทต่างๆ ทั้ง web mobile และ desktop application
จุดเด่นของ OAuth 2.0 คือ
- มีกระบวนการที่ง่ายและตรงไปตรงมากกว่า OAuth 1.0 โดยใช้ Access Token เพียงอย่างเดียว
- ไม่จำเป็นต้องใช้ Cryptographic Signature ทำให้ง่ายต่อการนำไปใช้งาน
- รองรับการอนุญาตแบบ Interactive (มีการโต้ตอบ) เช่น การแสดงหน้าจอให้ผู้ใช้อนุญาต
- มีการกำหนดการไหลของข้อมูล (Flow) ที่แตกต่างกันสำหรับประเภทของ application แต่ละแบบได้ เช่น Web Application Flow, Mobile Application Flow
โดย OAuth 2.0 ถือว่าดีกว่า OAuth 1.0 ในหลายๆ ด้าน ซึ่งนอกเหนือจากจุดเด่นเหล่านี้แล้ว
- OAuth 2.0 เป็นมาตรฐาน ที่มีการแบ่งแยกบทบาทหน้าที่ระหว่าง Authorization Server และ Resource Server อย่างชัดเจน ซึ่งช่วยเพิ่มความยืดหยุ่นและความปลอดภัยในการจัดการสิทธิ์การเข้าถึงข้อมูล
- รวมถึง OAuth 2.0 ถูกออกแบบมาให้มีประสิทธิภาพดีกว่าในการทำงานกับระบบขนาดใหญ่ที่มีผู้ใช้งานจำนวนมาก โดยใช้ Bearer Token ซึ่งง่ายต่อการตรวจสอบและมีประสิทธิภาพสูงกว่าการใช้ Cryptographic Signature ของ OAuth 1.0
ดังนั้นในปัจจุบัน เกือบทุกเจ้าจึงขยับมาใช้งานเป็น OAuth 2.0 แทน เพื่อให้เห็นภาพมากขึ้น เราจะลองมาดูวิธี implement OAuth 2.0 ทั้ง 4 ประเภทกัน
Oauth Grant Type ทั้ง 6 แบบ
ใน OAuth 2.0 มีการกำหนด “Grant Type” หรือวิธีการอนุญาตสิทธิ์ไว้หลายประเภท เพื่อรองรับการใช้งานกับ application ประเภทต่างๆ เพื่อให้สะดวกในแต่ละ use case ที่มีรูปแบบการ Authentication ที่แตกต่างกัน (และการใช้งานที่แตกต่างกัน) โดยแต่ละ use case จะมีการใช้งานประมาณนี้
Authorization Code Flow
Authorization Code Flow เป็นหนึ่งในวิธีการอนุญาตสิทธิ์ (Grant Type) ที่เหมาะสำหรับ application ที่มี Server อยู่ด้านหลังซึ่งสามารถเก็บ Client Secret ได้อย่างปลอดภัยไว้ได้
หลักการคือ
- ผู้ใช้เปิด application และ request เพื่อใช้งาน Resource ในระบบ
- application จะส่งคำขอไปยัง Authorization Server เพื่อขอ Authorization Code (เรียกเล่นๆว่า รหัสขอเข้าใช้งาน)
- Authorization Server จะแสดงหน้าจอให้ผู้ใช้อนุญาตหรือปฏิเสธการเข้าถึง Resource (หน้า Consent)
- หากผู้ใช้อนุญาต Authorization Server จะส่ง Authorization Code กลับไปยัง application
- application จะแลกเปลี่ยน Authorization Code นี้เพื่อขอ Access Token จาก Authorization Server
- เมื่อได้รับ Access Token แล้ว application จะใช้ Access Token นี้ในการเข้าถึง Resource จาก Resource Server ได้
- Resource Server ก็จะตรวจสอบ Access Token และส่งข้อมูล Resource ที่ request กลับไปยัง application
ไอเดียการ implement ก็จะประมาณนี้ ซึ่งข้อดีของ Authorization Code Flow คือ
- application ไม่ได้รับ Access Token โดยตรงจากผู้ใช้ ทำให้ Access Token ไม่โดนมองเห็นจากผู้ใช้หรือ Browser ได้ (มันไปแลกเปลี่ยนกันที่ Server ด้านหลัง)
- การแลกเปลี่ยน Authorization Code เพื่อขอ Access Token สามารถ verify ได้ด้วย Client Secret (ที่เก็บอยู่ใน Server ออกโดย Service Provider ของแต่ละเจ้าที่กำลังทำ OAuth) ซึ่งลดความเสี่ยงจากการถูกปลอมแปลงได้
- มีการแบ่งแยก Role หน้าที่ระหว่าง Authorization Server และ Resource Server อย่างชัดเจน เพิ่มความปลอดภัยและยืดหยุ่น
ในบรรดาทุกวิธี นี่เป็นวิธีการที่เป็นที่นิยมที่สุด เนื่องจาก implement ไม่ยาก รวมถึงมีความปลอดภัยด้วยไอเดียของการ implementation อยู่แล้ว
Password
Password Credentials Grant เป็นหนึ่งในวิธีการอนุญาตสิทธิ์ (Grant Type) ที่ง่ายที่สุด แต่ก็มีความเสี่ยงด้านความปลอดภัยสูง เนื่องจากเป็นการส่ง credential เข้าไปยัง Request โดยตรงของ Authorization Server แทนที่จะไปจัดการ Authentication ผ่าน Authorization Server
หลักการคือ
- ผู้ใช้จะ input ชื่อผู้ใช้และรหัสผ่านลงใน application
- application จะส่งชื่อผู้ใช้และรหัสผ่านนี้ไปยัง Authorization Server เพื่อขอ Access Token
- Authorization Server จะตรวจสอบชื่อผู้ใช้และรหัสผ่าน และหากถูกต้องจะออก Access Token ให้กับ application
- เมื่อได้รับ Access Token แล้ว application จะใช้ Access Token นี้ในการเข้าถึงResource จาก Resource Server
- Resource Server จะตรวจสอบ Access Token และส่งข้อมูล Resource ที่ร้องขอกลับไปยัง application
ข้อดีคือมันง่าย แต่ก็ตามมาด้วยข้อเสียหลายข้อตั้งแต่
- application จะได้รับข้อมูล Authentication ที่เป็นความลับของผู้ใช้ เช่น รหัสผ่าน ผ่านการกรองบน application (หรือการผ่านทาง Server ของ application)
- ไม่เหมาะสำหรับ application ที่ต้องการความน่าเชื่อถือสูง เนื่องจาก application จะสามารถเข้าถึงข้อมูลของผู้ใช้ได้โดยตรง
- ขัดกับหลักการของ OAuth ที่ไม่ควรแชร์ข้อมูลรับรองความถูกต้องที่เป็นความลับกับ application ไปยังบุคคลที่สาม
ด้วยเหตุผลเหล่านี้ Password Credentials Grant จึงไม่ค่อยได้รับความนิยมมากนัก และมักใช้เฉพาะกับ application ที่เชื่อถือได้เท่านั้น เช่น application ภายในองค์กร หรือ application ที่พัฒนาโดยตัวผู้ให้บริการเอง (มันจะให้อารมณ์คล้ายๆเหมือนเวลาเราทำ Authentication ที่ Server ตัวเองนั่นแหละ)
Client Credential
Client Credentials Grant เป็นหนึ่งในวิธีการอนุญาตสิทธิ์ (Grant Type) ที่ใช้สำหรับ application ในการเข้าถึง Resource ของระบบตัวเอง โดยไม่เกี่ยวข้องกับ user เป็นเหมือนการสร้าง “ตัวแทน” ของการพูดคุยขึ้นมา และจะทำการ Authorization ในฐานะ “ตัวแทน” ของสิ่งที่สร้างมาแทน
หลักการคือ
- application (Client) จะส่งคำขอไปยัง Authorization Server โดยระบุ Client ID และ Client Secret ซึ่งเป็นข้อมูล Authentication ของ application (ที่ตกลงกับ Service Provider ไว้)
- Authorization Server จะตรวจสอบ Client ID และ Client Secret หากถูกต้องจะออก Access Token ให้กับ application
- application จะใช้ Access Token ที่ได้รับ ในการเข้าถึง Resource ใน Resource Server โดยแนบ Access Token ไปพร้อมกับ request
- Resource Server จะตรวจสอบความถูกต้องของ Access Token และอนุญาตให้ application เข้าถึง Resource ที่ร้องขอได้เมื่อตรวจสอบเรียบร้อย
ทีนี้ อย่างที่เห็น ข้อดีของ Client Credentials Grant คือ
- ไม่มีการเกี่ยวข้องกับผู้ใช้ เนื่องจากเป็นการสื่อสารระหว่าง application หรือ service ด้วยกันเอง จึงไม่จำเป็นต้องมีการ Authentication ของผู้ใช้หรือขออนุญาตจากผู้ใช้
- การไม่มีขั้นตอนการโต้ตอบกับผู้ใช้ (ไม่มีส่วนหน้าจอสำหรับ Consent ขออนุญาต) ทำให้เหมาะสำหรับการทำงานแบบอัตโนมัติได้ด้วย
- สามารถกำหนดสิทธิ์การเข้าถึง Resource ได้อย่างละเอียดสำหรับแต่ละ application
เคสนี้ถ้าพูดแบบตามความรู้สึกเลย “มันเหมือนกับการเอา username กับ password” มาฝากไว้เลย เพื่อทำ Authentication ทีนี้ ข้อควรระวังในการใช้ Client Credentials Grant ก็จะมี
- ความปลอดภัยของ Client Secret เนื่องจาก application จะต้องเก็บ Client ID และ Client Secret ไว้เพื่อใช้ในการขอ Access Token จึงต้องระมัดระวังในการรักษาความปลอดภัยของ Client Secret ไม่ให้หลุดออกไปได้ (เพราะฉะนั้น จะใช้กับฝั่ง Client ที่เป็น web Frontend ไม่ได้)
- Client Credentials Grant ใช้สำหรับการเข้าถึง Resource ในนามของ “application” ไม่ใช่ในนามของผู้ใช้ ดังนั้น ระมัดระวังเรื่องการเข้าถึง Resource ของผู้ใช้โดยตรง เพราะอาจจะมี “สิทธิที่สูงกว่า” จนส่งผลกระทบต่อ data ของผู้ใช้ได้
ดังนั้น เมื่อพิจารณาประโยชน์และ จุดควรระวัง use case ที่เหมาะสมกับ Client Credentials Grant ก็จะเป็นงานที่ “พูดคุยภายใน Service ด้านหลังโดยเฉพาะ โดยไม่มีส่วนเกี่ยวข้องกับผู้ใช้” เช่น การที่ application หนึ่งต้องเรียกใช้ API ของ application อื่นภายในองค์กรเดียวกัน, application ต้องการเข้าถึงบริการ cloud เพื่อจัดเก็บและดึงข้อมูลที่ใช้ในการทำงานของ application ออกมา, การใช้ Cron Job หรือ Scheduled Task ในการเรียกใช้ API เพื่อนำข้อมูลมาประมวลผล, อุปกรณ์ IoT ต้องส่งข้อมูลไปยังบริการ Cloud เพื่อประมวลผล เป็นต้น
Implicit
Implicit Grant เป็นหนึ่งในวิธีการอนุญาตสิทธิ์ (Grant Type) ที่ถูกออกแบบมาสำหรับ Browser application เช่น Single Page Application ที่ไม่สามารถเก็บ Client Secret ได้อย่างปลอดภัยไว้ได้
หลักการคือ
- ผู้ใช้เปิด Browser application และ request ขอใช้งาน Resource
- application จะส่งคำขอไปยัง Authorization Server เพื่อขอ Access Token
- Authorization Server ก็จะแสดงหน้าจอให้ผู้ใช้อนุญาตหรือปฏิเสธการเข้าถึง Resource
- หากผู้ใช้อนุญาต Authorization Server จะส่ง Access Token กลับไปยัง Browser application โดยตรง
- application จะใช้ Access Token ที่ได้รับในการเข้าถึง Resource จาก Resource Server
- Resource Server จะตรวจสอบ Access Token และส่งข้อมูล Resource ที่ request กลับไปยัง application ได้
ซึ่งอย่างที่เห็น ถ้าเล่าแบบง่ายๆคือ “คล้าย Authorization Code Flow แต่ตัด Server ออก” ข้อดีใหญ่ๆของวิธีนี้คือ กระบวนการง่ายและมีขั้นตอนน้อยกว่า Authorization Code Grant แต่ก็จะมีข้อพิจารณาต่างๆคือ
- Access Token จะถูกส่งกลับไปยัง Browser application บราว์เซอร์โดยตรง ซึ่งอาจมีความเสี่ยงในการถูกขโมยได้
- ไม่สามารถใช้ Refresh Token ในการขอ Access Token ใหม่ได้ เมื่อ Access Token หมดอายุ application จะต้องผ่านกระบวนการขออนุญาตจากผู้ใช้ใหม่แทน
ตามหลักการแล้ว Implicit ถือว่ามีความปลอดภัยน้อยกว่า Authorization Code Grant ด้วยเหตุนี้ Implicit Grant จึงไม่ค่อยได้รับความนิยมมากนักในปัจจุบัน และมักจะใช้ Authorization Code Grant แทนสำหรับ application ที่ สามารถเก็บ Client Secret ได้อย่างปลอดภัยบน Server ได้ (จะเหมาะกับเคสที่เว็บมีเพียงแค่ Client = SPA เท่านั้น)
Device Code
Device Code Grant เป็นหนึ่งในวิธีการอนุญาตสิทธิ์ (Grant Type) ที่ถูกออกแบบมาสำหรับอุปกรณ์ที่ไม่มี Browser หรือมีข้อจำกัดในการรับข้อมูลผ่านแป้นพิมพ์ เช่น อุปกรณ์ IoT, Smart TV เป็นต้น
หลักการคือ
- อุปกรณ์ส่งคำขอไปยัง Authorization Server เพื่อขอ Device Code และ User Code
- Authorization Server จะออก Device Code, User Code และ Verification URI ให้กับอุปกรณ์
- อุปกรณ์จะแสดง User Code และ Verification URI ให้กับผู้ใช้ และแนะนำให้ผู้ใช้ใช้อุปกรณ์อื่น (เช่น smart phone=) ในการเข้าสู่ Verification URI และ input User Code
- ผู้ใช้จะเข้าสู่ Verification URI ผ่าน Browser บนอุปกรณ์อื่น และป้อน User Code ที่ได้รับจากอุปกรณ์หลัก
- Authorization Server จะขอให้ผู้ใช้อนุญาตหรือปฏิเสธการเข้าถึง Resource สำหรับอุปกรณ์หลัก (อุปกรณ์ที่กำลัง Authentication อยู่)
- หากผู้ใช้อนุญาต Authorization Server จะบันทึกการอนุญาตนี้ไว้
- ในขณะเดียวกัน อุปกรณ์หลักจะเริ่มส่งคำขอไปยัง Authorization Server อย่างต่อเนื่อง (Polling) โดยใช้ Device Code เพื่อตรวจสอบว่าผู้ใช้อนุญาตแล้วหรือยัง
- เมื่อผู้ใช้อนุญาตแล้ว Authorization Server จะออก Access Token (และ Refresh Token ถ้ามี) ให้กับอุปกรณ์หลัก
- อุปกรณ์หลักจะใช้ Access Token ในการเข้าถึง Resource จาก Resource Server
- Resource Server จะตรวจสอบ Access Token และส่งข้อมูล Resource ที่ request กลับไปยังอุปกรณ์หลัก
ตามที่เล่าใน step implementation Device Code Grant ถูกออกแบบมาเพื่อแก้ปัญหาสำหรับอุปกรณ์ที่มีข้อจำกัดในการรับข้อมูลผ่านแป้นพิมพ์หรือไม่มี Brower โดยมีข้อดีคือ
- ผู้ใช้สามารถอนุญาตการเข้าถึงผ่านอุปกรณ์อื่นที่มีความสะดวกในการป้อนข้อมูลมากกว่า เช่น Smart phone หรือคอมพิวเตอร์
- อุปกรณ์ที่ไม่มี Browser หรือมีข้อจำกัดในการรับข้อมูลผ่านแป้นพิมพ์ ก็สามารถใช้ Device Code Grant ในการขออนุญาต (Authorization) ได้
- การแยกขั้นตอนการอนุญาตออกจากอุปกรณ์หลัก ช่วยลดความเสี่ยงจากการแอบดักข้อมูลบนอุปกรณ์นั้นได้
แต่ยังไงก็ตาม Device Code Grant ก็มีข้อเสียบางประการ เช่น ขั้นตอนการทำงานที่ซับซ้อนขึ้น และความจำเป็นที่ผู้ใช้จะต้องมีอุปกรณ์อื่นในการอนุญาต (ใช้ยากแหละเอาง่ายๆ) ดังนั้นจึงควรใช้ Device Code Grant เฉพาะกับอุปกรณ์ที่มีข้อจำกัดจริงๆ เท่านั้น
Refresh token
Refresh Token Grant เป็นหนึ่งในวิธีการอนุญาตสิทธิ์ (Grant Type) ที่ใช้สำหรับการขอ Access Token ใหม่เมื่อ Access Token เดิมหมดอายุ โดยไม่ต้องให้ผู้ใช้ผ่านกระบวนการรับรองความถูกต้องซ้ำอีกครั้ง
หลักการคือ
- เมื่อ Access Token ที่ application (Client) หมดอายุแล้ว application จะส่งคำขอไปยัง Authorization Server โดยระบุ Refresh Token ที่ได้รับมาก่อนหน้านี้
- Authorization Server จะตรวจสอบความถูกต้องของ Refresh Token หากถูกต้องจะออก Access Token ใหม่ให้กับ application
- นอกจากนี้ Authorization Server อาจออก Refresh Token ใหม่ให้ด้วย เพื่อใช้ในการขอ Access Token ครั้งต่อไปเมื่อ Access Token ที่ได้รับใหม่นี้หมดอายุ
การใช้ Refresh Token ช่วยให้ application สามารถขอ Access Token ใหม่ได้โดยไม่ต้องให้ผู้ใช้ผ่านกระบวนการรับรองความถูกต้องซ้ำอีกครั้ง (ไม่ต้องไปคอย login ใหม่) ทำให้ประสบการณ์การใช้งานของผู้ใช้ดีขึ้น ซึ่งนี่เป็นข้อดีของ Refresh Token Grant รวมถึง สามารถจำกัดเวลาของการใช้ Access Token ที่มีอายุลดลงได้ เพื่อช่วยลดความเสี่ยงจากการใช้งาน Access Token ที่อาจจะรั่วไหลไปได้ (จากการแบ่งหน้าที่ให้ Refresh Token เป็นคนคอยออก Token ใหม่ให้แทน)
อย่างไรก็ตาม Refresh Token ก็มีข้อเสียอยู่นะ เช่น ความเสี่ยงจากการรั่วไหลของ Refresh Token และการจัดเก็บ Refresh Token ให้ปลอดภัย ดังนั้นจึงควรใช้ Refresh Token Grant ร่วมกับ standard security อื่นๆด้วย เช่น การใช้งาน HTTPS, เช็คว่า access token ตัวเก่าถูกออกจากระบบนี้จริงๆหรือไม่ รวมถึง การกำหนดอายุการใช้งานของ Refresh Token เอาไว้ด้วย เป็นต้น
และนี่ก็คือ 6 grant type ของ OAuth ที่ใช้สำหรับการทำ Authorization ประเภทต่างๆ แต่ละแบบก็จะมี ข้อดี / เสีย use case ต่างๆกันไป ก่อนใช้ ให้ศึกษา use case ที่เหมาะสมก่อนจะใช้งานร่วมกันด้วยนะครับ
Oauth กับ RBAC
RBAC หรือ Role-Based Access Control เป็นวิธีการควบคุมการเข้าถึงโดยการกำหนดสิทธิ์ให้กับผู้ใช้ตามบทบาทหน้าที่ (Role) แทนที่จะกำหนดสิทธิ์ให้กับผู้ใช้แต่ละคน
โดยในระบบ RBAC จะมีการสร้างบทบาทหน้าที่ต่างๆ ขึ้นมา เช่น บทบาทผู้ดูแลระบบ (admin) บทบาทผู้ใช้ทั่วไป (user) เป็นต้น แล้วกำหนดสิทธิ์การเข้าถึง Resource ต่างๆ ให้กับบทบาทเหล่านั้น เมื่อมีผู้ใช้คนใหม่เข้ามา ก็จะมอบบทบาทให้กับผู้ใช้คนนั้นตามหน้าที่ความรับผิดชอบ ผู้ใช้จะได้รับสิทธิ์ตามบทบาทที่ได้รับมอบหมายและเข้าถึง Resource ได้ตามที่บทบาทกำหนดไว้นั่นเอง
เมื่อนำ OAuth มาใช้ร่วมกับ RBAC จะช่วยเพิ่มความปลอดภัยและการควบคุมการเข้าถึง Resource ได้ตั้งแต่
- การกำหนดสิทธิ์การเข้าถึงด้วย Scopes ใน OAuth สามารถกำหนด Scopes หรือขอบเขตของสิทธิ์การเข้าถึงได้ เมื่อผู้ใช้อนุญาตให้ application เข้าถึงข้อมูลหรือ Resource Access Token ที่ออกจะมี Scopes แนบมาด้วย ทำให้สามารถควบคุมได้ว่า application นั้นสามารถเข้าถึงข้อมูลหรือ Resource ใดได้บ้าง
- การกำหนดสิทธิ์ตาม Role ด้วย Custom Claims นอกจากใช้ Scopes แล้ว ยังสามารถใส่ข้อมูลบทบาทหน้าที่ (Role) ของผู้ใช้ลงใน Access Token ด้วย โดยใช้ Custom Claims ทำให้ Resource server สามารถตรวจสอบบทบาทของผู้ใช้และกำหนดสิทธิ์การเข้าถึงตามบทบาทนั้นได้
- การแบ่งแยกบทบาทหน้าที่ OAuth ช่วยแบ่งแยกบทบาทหน้าที่ระหว่าง Authorization Server และ Resource Server ออกจากกัน ทำให้สามารถจัดการสิทธิ์การเข้าถึงได้อย่างยืดหยุ่นและปลอดภัยมากขึ้น
- รวมถึง OAuth สามารถใช้งานร่วมกับ ABAC (Attribute-Based Access Control) ได้ โดยใช้ข้อมูลคุณลักษณะต่างๆ ของผู้ใช้ เช่น บทบาท สถานะ ในการกำหนดสิทธิ์การเข้าถึง Resource นั้นๆ
ตัวอย่างการแนบและการใช้งานเช่น
หลักการ
- ผู้ใช้เปิด application และร้องขอเข้าถึง Resource (และทำ Authorization จนได้ Access Code ออกมา เหมือนกับหัวข้อก่อนหน้านี้)
- application แลกเปลี่ยน Authorization Code เพื่อขอ Access Token จาก Authorization Server
- Authorization Server จะตรวจสอบบทบาทหน้าที่ (Role) ของผู้ใช้ จากนั้นจะออก Access Token พร้อมแนบข้อมูล Role ของผู้ใช้ไว้ใน Custom Claims
- ในฝั่งของ application ใช้ Access Token ในการเข้าถึง Resource จาก Resource Server
- Resource Server จะตรวจสอบ Role ที่แนบมากับ Access Token
- Resource Server จะอนุญาตให้ application เข้าถึง Resource ตามสิทธิ์ของ Role นั้น และส่งข้อมูล Resource กลับไปยัง application
ในตัวอย่างนี้ Authorization Server จะแนบข้อมูล Role ของผู้ใช้ลงใน Access Token โดยใช้ Custom Claims ซึ่งเป็นคุณสมบัติของ JWT (JSON Web Token) ที่ใช้เป็น Access Token ได้ เมื่อ application นำ Access Token ไปใช้เข้าถึง Resource ตัว Resource server จะตรวจสอบ Role ที่แนบมาใน Access Token และอนุญาตให้เข้าถึง Resource ตามสิทธิ์ของ Role นั้นได้
และนี่คือตัวอย่างของข้อมูลที่แปะมากับ access token ผ่าน Custom Claims ใน JWT
ในตัวอย่างนี้ เรามี Custom Claims 2 ส่วน คือ
- roles เป็น Array ของบทบาทหน้าที่ (Role) ของผู้ใช้ ในที่นี้ผู้ใช้มีบทบาท “admin” และ “editor”
- permissions เป็น Array ของสิทธิ์การเข้าถึง (Permission) ที่ผู้ใช้มี ในที่นี้ผู้ใช้มีสิทธิ์ “read”, “write” และ “delete”
เมื่อ application นำ Access Token ไปใช้เข้าถึง Resource ตัว Resource server ก็จะสามารถตรวจสอบข้อมูล Role และ Permission ที่แนบมาใน Payload ของ Access Token ได้ จากนั้นจะอนุญาตหรือปฏิเสธการเข้าถึง Resource ตามสิทธิ์ของผู้ใช้ได้ ตาม application logic ของเราอีกที
ถ้าเป็นตัวอย่าง payload ที่ดึงจาก jwt ฉบับ ก็จะได้ข้อมูลออกมาประมาณนี้ (สำหรับการยืนยันและการแกะข้อมูล JWT สามารถดูผ่านหัวข้อ Authentication ในช่อง mikelopster เพิ่มเติมได้)
และด้วยไอเดียนี่เอง ก็จะทำให้เราสามารถสร้างระบบที่สามารถทั้งยืนยันตัวตนได้ และสามารถกำหนดบทบาทการใช้งานผ่าน Access token ในคราวเดียวกันออกมาได้นั่นเอง
สรุป
สรุปก็คือ OAuth เป็นมาตรฐานที่ใช้ในการอนุญาตการเข้าถึง Resource และข้อมูล โดยมีแนวคิดหลักคือการแยกการรับรองความถูกต้อง (Authentication) ออกจากการอนุญาต (Authorization) ซึ่งช่วยเพิ่มความปลอดภัยและความเป็นส่วนตัวเพิ่มขึ้น โดย OAuth 2.0 นั้นได้กำหนดวิธีการอนุญาตสิทธิ์หรือที่เรียกว่า Grant Type ไว้หลายประเภท เพื่อรองรับการใช้งานกับ application ใน use case ประเภทต่างๆไว้
โดย Grant Type ที่สำคัญและนิยมใช้ ได้แก่ Authorization Code Grant, Implicit Grant, Resource Owner Password Credentials Grant และ Client Credentials Grant แต่ละ Grant Type มีขั้นตอนและวิธีการที่แตกต่างกันไป เพื่อให้เหมาะสมกับ Architecture ของระบบและความต้องการด้านความปลอดภัย โดยทั่วไปแนะนำให้ใช้ Authorization Code Grant เนื่องจากมีความปลอดภัยสูงสุดในบรรดาทุกเคส (เช็คทุกอย่างก่อนที่จะได้ access token มา)
นอกจากนี้ OAuth ยังสามารถนำมาใช้ร่วมกับ RBAC (Role-Based Access Control) ได้ โดยการกำหนดสิทธิ์การเข้าถึงลงใน Access Token ด้วย Custom Claims หรือการใช้ Scopes ในการระบุขอบเขตของสิทธิ์ที่ได้รับอนุญาตลงคู่ไว้ใน Access Token ทำให้สามารถควบคุมการเข้าถึง Resource ได้อย่างละเอียดตามบทบาทหน้าที่ของผู้ใช้ ช่วยเพิ่มความปลอดภัยและการควบคุมการเข้าถึงข้อมูลได้อย่างมีประสิทธิภาพมากขึ้น
และนี่คือก็ OAuth หวังว่าบทความนี้จะช่วยทำให้เข้าใจ OAuth กันได้ดียิ่งขึ้นนะครับ (ไว้เดี๋ยวเราจะหาหัวข้อลง detail การ implementation OAuth กันเพิ่มเติมนะครับ)