เค้าออกเสียง OAuth กันว่า [โอ-อ๊อด] บางคนบอกว่ามันเป็น flow ของการ login เหมือนเวลา login app ด้วย Google account บ้างก็บอกว่าเป็นอะไรที่เกี่ยวกับเรื่องความปลอดภัย (security) แล้วก็บอกได้แค่นั้นแหละ
OAuth คือ
OAuth มันไม่ใช่ API ไม่ใช่ service แต่เป็นมาตราฐานแบบเปิดเกี่ยวกับการยืนยันสิทธิ์ (Authentication) การจัดการสิทธิ์การใช้ระบบ (Authorization) ซึ่งนักพัฒนาเอามาใช้งานจริงได้ เป็นมาตราฐานที่แอพพลิเคชั่นจะใช้ติดต่อกับเครื่อง client ในแบบการเข้าระบบผ่านตัวแทนที่ปลอดภัย (secure delegated access) …ห๊ะ มันอะไรกัน secure delegated access ลองอ่านต่อไปก่อนนะครับแล้วน่าจะเข้าใจ
OAuth ทำงานผ่าน HTTP และอุปกรณ์ที่ได้รับอนุญาต หรือทำงานผ่าน APIs, เซิฟเวอร์, แอพ ที่ได้รับอนุญาต โดยใช้สิ่งที่เรียกว่า access token [แอคเซส โทคเค่น] แทนรหัสผ่าน/พาสเวิร์ด OAuth มี 2 เวอร์ชั่น มี 1.0a กับ 2 ซึ่งใช้ด้วยกันไม่ได้เลย เสปคไม่เหมือนกัน -__- อ่าว
OAuth ทำอะไรได้
ว่ากันง่ายๆ OAuth เป็น protocol ที่รองรับ flow หรือเส้นทางในการยืนยันสิทธิ์ ทำให้มั่นใจได้ว่า ผู้ใช้คนใดๆมีสิทธิ์ที่จะทำอะไรๆได้บ้าง OAuth มันทำแค่นี้จริงๆ ไม่เกี่ยวกับเรื่องการ login เลย มันไม่ได้เกี่ยวกับเรื่องการตรวจสอบการ login หรืออะไรทำนองนั้นนะ
อ่านมาถึงตรงนี้อาจจะสงสัยว่า protocol ที่ทับศัพท์เนี่ยมันแปลว่าอะไร ในที่นี้จะหมายความประมาณว่า พิธีการ/วิธีการ
ในโพสนี้จะพูดกันถึง OAuth version 2 ก่อน
OAuth 2 ทำงานอย่างไร
มีการทำงาน 4 แบบ เรียก grant_type ขึ้นอยู่กับว่าเราจะเอาไปทำ service แบบไหน อาจจะใช้แต่ละแบบร่วมกันก็ได้ ไม่ได้มีการจำกัดไว้
1 Authorization Code
เอาไว้ใช้กับ web server ถ้าเราสร้าง web application โค๊ดส่วนที่เป็น back-end ก็คือส่วนที่ไม่ได้เปิดเผยให้สาธารณะเห็น จะใช้ OAuth แบบนี้ ตัวอย่างเช่นโค้ดใน Express.js, Django, Ruby on Rail
ทำงานอย่างไร
- ผู้ใช้ทั่วไปมาที่เวบไซต์
- พวกเขาใช้บริการ login จาก account ของระบบอื่นๆ เช่น Facebook, Twitter, Google, etc.
- คลิกปุ่ม login แล้วผู้ใช้จะถูกพาไปยังหน้า login ของผู้ให้บริการนั้นๆ และจะถูกแนะนำสิทธิที่ผุ้ใช้จะถูกแอพเรียกใช้งาน
- ถ้าผู้ใช้ ยอมรับข้อนุญาตเหล่านั้น ผู้ให้บริการ จะพากลับไปยังเว็บ แอพพลิเคชั้นนั้นๆ พร้อมทั้งส่ง authorization code มาให้ด้วย
- เมื่อ server ได้รับ authorizatoin code จะติดต่อไปยัง indentity provider เพื่อดูว่าทำอะไรได้บ้าง หรือมีสิทธิทำอะไร
วิธีใช้ authorization code
- มีปุ่ม login ซึ่งมี link มี parameter คล้ายๆแบบนี้
https://login.blah.com/oauth?response_type=code&client_id=xxx&redirect_uri=xxx&scope=email
- เมื่อกดปุ่ม login ระบบจะต้องแจ้งว่า จะขอใช้สิทธิเรื่องใดบ้าง
- เมื่อผู้ใช้กดตกลงอนุญาต หน้าจอจะถูกพาไปยัง redirect_uri ที่ระบุไว้ พร้อมทั้งส่ง authorization code มาให้ด้วย
- ซึ่งจะมีหน้าตาประมาณนี้
https://yoursite.com/oauth/callback?code=xxx
- อ่าน code ออกมาเพื่อนำไปขอ access_token กับ API ของผู้ให้บริการ login ตัวนั้นๆ
POST https://api.blah.com/oauth/token?grant_type=authorization_code&code=xxx&redirect_uri=xxx&client_id=xxx&client_secret=xxx
ค่า client_id
, client_secret
โดยมาก เจ้าของ login API (Identity provider) จะเป็นคนกำหนดมาให้
หลังจากส่ง code ด้วย HTTP method POST และบอกว่าเป็น grant_type
แบบ authorization_code
ไปแล้ว client จะได้ access_token
กลับมา เราจะเอา access_token
นั้นในการเรียก API ต่อๆไปได้ เช่น เอาข้อมูล user มาได้
2 Implicit
กำหนดมาเพื่อเอาไว้ใช้ในฝั่งของ client ของ web application (เช่นใน ReactJS, AngularJS) ฝั่งซึ่งไม่มี compoment ของ server หรือการใช้ mobile web browserในการติดต่อกับ server เป็นวิธีที่ client ไม่ต้องเก็บข้อมูลลับอะไร (secret key)
เราสามารถให้ผู้ใช้ ใช้งาน web application ของเราได้โดยที่ไม่จำเป็นต้องรู้ว่า client_secret
คืออะไร
ทำงานอย่างไร
- ผู้ใช้นิรนามเปิดหน้าเวบไซด์ของเรา
- พวกเขาต้องการใช้บริการ id provider ของผู้ให้บริการอื่น เช่น Facebook, Google หรือ OAuth service ที่เราสร้างขึ้น
- เมื่อพวกเขากดปุ่ม login หน้าเวบจะ redirect ไปยังหน้าแสดงขอใช้สิทธิของผู้ให้บริการนั้นๆ หากผู้ใช้ยอมรับ มันก็จะ redirect กลับมาที่หน้าของระบบเราอีกครั้งหนึ่งพร้อมทั้ง
access_token
- เราสามารถใช้
access_token
นี้เพื่อค้นหาเอา ข้อมูลผู้ใช้ที่ต้องการออกมาได้
วิธีใช้ Implicit
- สร้างปุ่ม login ที่ส่ง action ไปยัง URL แบบนี้
https://login.blah.com/oauth?response_type=token&client_id=xxx&redirect_uri=xxx&scope=email
- เมื่อผู้ใช้กดปุ่ม จะแสดงหน้าต่างขอใช้สิทธิ หากตกลงข้อมูลจะ submit ไป server แล้วข้อมูล token จะถูกส่งกลับมาตาม
redirect_uri
ที่กำหนดเอา client_id
ในข้อ 1 id provider เป็นคนกำหนดมาให้- token ที่ได้มา เอาไปใช้ได้ดึงข้อมูลตามสิทธิ์ที่ได้มาได้เลย
3 Password Credentials
ใช้สำหรับ web application หรือ mobile application ที่เป็นทางการของเราเอง เพราะเราสามารถจัดการสิทธิต่างๆได้เพียงแค่ถาม username กับ password ซึ่งวิธีอื่นจะต้องใช้การ redirect ไปมา
ถ้าคุณมีหรือสร้าง OAuth service ของตัวเอง หรือมี OAuth client app ของตัวเอง คุณจะใช้ grant type แบบนี้ได้ ไม่ว่าจะเป็นใน Android, iOS หรือ web apps ก็ได้
แต่ข้อสำคัญคือ เราจะใช้ OAuth service แบบนี้ภายใน app ของเราเท่านั้น ไม่ได้ให้คนอื่นๆมาใช้
เช่น หากเราเป็น Google มี app ของเราเอง ก็ให้ผู้ใช้ login เข้าระบบของเราด้วย username/password ของเขาเอง แต่ไม่ใช่ไปใส่ username/password ผ่านทาง server ของเวบไซด์อื่นซึ่ง เขาอาจจะเอา username/password ไปใช้ในทางที่ไม่ดีได้
ทำงานอย่างไร
- ผู้ใช้นิรนามเปิดหน้าจอเข้าสู่ระบบ
- ต้องการจะใช้ username/password ที่มีอยู่เข้าระบบ (ซึ่งเก็บไว้ภายใต้ OAuth service ที่ทำไว้)
- เอาข้อมูล username/password เรียกผ่าน API call ถ้าเข้าได้ก็ส่ง
acess_token
มาให้ - นำ
access_token
ไปใช้งานได้
การใช้ Password Credentials
- มี form รับ username/password เมื่อกด submit แล้ว ส่ง form submit (POST method) ไปยัง server/service ของเรา
POST https://login.blah.com/oauth/token?grant_type=password&username=xxx&password=xxx&client_id=xxx
- จะได้
access_token
มาใช้งานได้เลยหากใส่ข้อมูลถูกต้อง
4 Client Credentials
เพื่อใช้ใน code ฝั่ง client เราจะใช้ client credential เมื่อเราต้องการทำงานบางอย่างโดยที่ไม่เกี่ยวกับผู้ใช้ ใช้ใน background taskในแอพ ของเรา เช่น เราอยากจะ update metadata ของแอพเรา หรืออ่าน metric/insights ของแอพเรา
ทำงานอย่างไร
- client เรียกใช้ API ไปยัง id provider
POST https://login.blah.com/oauth/token?grant_type=client_credentials&client_id=xxx&client_secret=xxx
แล้ว client นั้นจะได้ access_token
มาใช้
client_id
,client_secret
ทาง Id provider จะเป็นผู้กำหนดมาให้
OAuth 2 ปลอดภัยหรือไม่?
ตอบเลยว่า ไม่ โดยวิธีการของมันไม่ได้ปลอดภัย แต่เราจะต้องเสริมการป้องกันเข้าไปเวลาใช้งาน ถ้าจะใช้รับส่งข้อมูลสำคัญ (Sensitive data) ให้ใช้ OAuth 1.0a มันมีความปลอดภัยมากกว่า
เมื่อไหร่ควรใช้ OAuth?
เมื่อเรากำลังสร้าง service ที่จะต้องใช้ข้อมูลสำคัญของผู้ใช้ ซึ่งถูกเก็บเอาไว้ในอีกระบบหนึ่ง
การป้องกัน REST API ป้องกัน OAuth อย่างถูกวิธี Strompath ผู้ซึ่งให้บริการ platform ทางด้าน Authentication,Authorization ได้สรุปแนวทางป้องกัน API เอาไว้ดังนี้ (เขาต้องทำ API ของตนเองให้ปลอดภัยเช่นกัน)
ให้เลือกใช้ protocol ที่เป็นมาตราฐานในอุตสาหกรรมนี้จะดีกว่า จะทำให้ไม่ต้องเสียเวลาไปมากกับการคิดค้นใหม่ เว้นว่าจะต้องการ protocol ในลักษณะพิเศษ
ด้านล่างนี้เป็นสรุป, บอกข้อดีข้อเสีย ของ protocol ที่นิยมใช้กัน
Basic Authentication กับ TLS
เป็น protocol ที่ง่ายที่สุดแล้ว ไม่ต้องใช้ library พิเศษอะไร แค่ submit form หรือส่งข้อมูล username/password ไปยัง server จะปลอดภัยขึ้นมาอีกหน่อยคือส่งผ่าน HTTPS(TLS) แต่ถ้าหากโดนดักจับไปได้ก็สามารถแปลง base64 กลับมาเห็น username กับ password ได้เลย
OAuth1.0a
เป็น protocol วิธีที่ปลอดภัยที่สุดในใน 3 แบบที่นำเสนอ OAuth1 ถูกใช้อย่างแพร่หลาย ได้รับการทดสอบแล้ว มีความปลอดภัย เป็น protocol ที่อิงกับลายเซ็น (signature-based)
protocol จะใช้ลายเซ็นเข้ารหัส ด้วย HMAC-SHA1
เป็นค่าที่ประกอบมาจาก token secret, nonce และข้อมูลอื่นๆ เราไม่ต้องส่ง token secret ไปมากับ server ทำให้การที่ token secret จะหลุดเป็นไปได้ยาก การรับส่งไม่จำเป็นต้องใช้ HTTPS ด้วยซ้ำ แต่ถึงอย่างไรเราก็ควรใช้ HTTPS อยู่ดี หากเราส่งข้อมูลที่ sensitive
ความปลอดภัยสูงของ OAuth 1 นี้ ต้องแลกกับกระบวนการที่ซับซ้อน เวลาสร้าง และตรวจสอบความถูกต้องของลายเซ็นต์ แต่ทุกวันนี้ library ในแต่ละภาษายอดนิยมมีเครื่องมือเอาไว้รองรับเรื่องพวกนี้แล้ว
OAuth2
อ่านชื่อแล้วอาจจะคิดว่าเป็นตัวที่พัฒนาต่อมาจาก OAuth 1 แต่ไม่ใช่เลย มันลดความซับซ้อนด้านความปลอดภัยลงจาก OAuth 1 ในเสปคของ OAuth 2 ตอนนี้ เอาส่วนที่เป็นลายเซ็นออก เราไม่จำเป็นต้องใช้การเข้ารหัสเพื่อที่จะสร้าง,ตรวจสอบลายเซ็น การเข้ารหัสให้เป็นหน้าที่ของ TLS ซึ่งเป็นสิ่งจำเป็นสำหรับ OAuth 2
ยังมี library สำหรับ OAuth2 ไม่มากนัก ดังนั้นการนำมาใช้งานกับ API ของเราอาจจะเป็นงานที่ท้าทาย
สำหรับการรับส่งข้อมูลที่ sensitive แนะนำให้ใช้ OAuth 1 จะดีกว่า ส่วน OAuth 2 น่าจะเหมาะกับการรับส่งข้อมูลที่ไม่สำคัญมากนัก อย่างเช่นข้อมูลใน social network
Protocol ที่คิดค้นเอง
การทำ protocol สำหรับ authentication เองนั้นควรหลีกเลี่ยง เว้นแต่จำเป็นจริงๆ และคุณรู้ว่าคุณกำลังทำอะไรอยู่ และคุณเข้าใจเรื่องการเข้ารหัสอย่างถ่องแท้ องค์กรส่วนใหญ่ไม่มีผู้เชี่ยวชาญด้านนี้หรอก ดังนั้นเขาแนะนำให้ใช้ OAuth1.0a จะดีกว่า
และเมื่อคุณทำมันขึ้นมาเอง ข้อเสียอีกอย่างก็คือ การนำไปใช้จะยากไม่มีใครนำไปใช้ได้ง่ายๆ นอกจากองค์กรหรือคุณเอง เมื่อใช้ custom protocol คุณต้องคอยช่วยเหลือหรือสร้าง library สำหรับภาษาต่างๆ ที่จะมาเรียกใช้ API ของคุณให้ได้ ทำให้ใช้ได้ง่ายหรือแทบไม่ต้องออกแรง เพราะถ้าหากไม่มีตัวช่วยเหลือ API ก็จะไม่มีคนใช้ในที่สุด
Note: Blog โพสนี้เรียบเรียงมาจาก What the Heck is OAuth? ของ Stormpath
ศึกษาเพิ่มเติม:
- Introducing OAuth 2.0
- [oauth Bible](the oauth bible)