• oidc
  • oauth
  • authentication
  • authorization
  • jwt

คู่มือสมบูรณ์ในการผนวกรวม OIDC เซิร์ฟเวอร์เข้ากับโปรเจคของคุณ

เรียนรู้แนวปฏิบัติที่ดีที่สุดในการผนวกรวม OIDC (OpenID Connect) เซิร์ฟเวอร์เข้ากับโปรเจคของคุณและทำความเข้าใจว่าคอมโพเนนต์ต่างๆ ทำงานร่วมกันบนเวทีอย่างไร

Gao
Gao
Founder

คุณอาจพบสถานการณ์ที่คุณต้องการระบบการสืบค้นตัวตนและการอนุญาตแบบศูนย์กลาง หรือที่เรียกกันว่า Identity Access Management (IAM) หรือ Identity Provider (IdP) บางครั้งคนจะเพิ่มคำเข้ามาเพื่อระบุธุรกิจ เช่น Customer IAM และ Workforce IAM

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

พิจารณาจากความนิยมของ OAuth 2.0, OpenID Connect (OIDC) จึงเป็นทางเลือกที่เป็นธรรมชาติสำหรับนักพัฒนาหลายๆ คน เนื่องจาก OIDC เป็นเลเยอร์การสืบค้นตัวตนที่ถูกสร้างขึ้นบน OAuth 2.0 คุณอาจรู้สึกคุ้นเคยเมื่อเริ่มทำงานกับ OIDC มากขึ้น มาเริ่มต้นกันเลย!

OIDC เซิร์ฟเวอร์คืออะไร และทำไมฉันควรผนวกรวม OIDC เซิร์ฟเวอร์?

OIDC เซิร์ฟเวอร์ หรือ Identity Provider เป็นระบบศูนย์กลางที่จัดการความปลอดภัยในการยืนยันตัวตนและการให้สิทธิ์เข้าถึงของผู้ใช้ ตามที่เราได้กล่าวถึงใน ทำไมคุณต้องมีระบบตัวตนแบบศูนย์กลางสำหรับธุรกิจหลายแอป ระบบตัวตนแบบศูนย์กลางมีประโยชน์หลายประการ

สมมติว่าปรเจคของคุณเริ่มต้นด้วยเว็บแอปพลิเคชันที่เรียบง่าย และมีการสืบค้นตัวตนในตัว:

เมื่อปรเจคของคุณเติบโตขึ้น คุณต้องแนะนำเวอร์ชั่นมือถือ:

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

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

หรือ ใช้เทคนิคโทเค็นบางชนิดในการสืบค้นตัวตนของผู้ใช้ และตรวจสอบความถูกต้องของโทเค็นด้วยการติดต่อกับเว็บแอปพลิเคชันในบริการ ดังนั้นแอปพลิเคชันมือถือสามารถใช้บริการได้โดยตรง:

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

กระบวนการรีแฟกเตอร์สามารถเป็นการเจ็บปวด คุณอาจสังเกตเห็นว่าความซับซ้อนของมันจะเพิ่มขึ้นอย่างรวดเร็วเมื่อคุณเพิ่มแอปพลิเคชันและบริการในโปรเจคมากขึ้น ยิ่งแย่ไปกว่านั้น คุณอาจต้องรักษาวิธีการสืบค้นตัวตนหลากหลายรูปแบบ เช่น การเข้าสู่ระบบโดยไม่ใช้รหัสผ่าน, การเข้าสู่ระบบโซเชียล, SAML เป็นต้น

นี่คือเหตุผลว่าทำไมน่าจะดีกว่าหากเราแนะนำ Identity Provider ต้นเมื่อคุณมีแผนที่จะขยายโปรเจคของคุณขึ้น

แนวปฏิบัติที่ดีที่สุดสำหรับการผนวกรวม OIDC เซิร์ฟเวอร์

ค้นหา OIDC Provider

มี OIDC Provider จำนวนมากในตลาด คุณสามารถเลือกหนึ่งตามความต้องการและความชอบของคุณ ตราบใดที่ผู้ให้บริการสอดคล้องกับ OIDC, มันจะทำบทบาทเดียวกันในโปรเจคของคุณ

“subject,” “client,” และ “audience” หมายความว่าอย่างไรใน OIDC?

เพื่อความง่ายในการทำความเข้าใจแนวคิด, เราสามารถนึกถึง subject เป็นหน่วยที่กำลังร้องขอการเข้าถึง audience ผ่าน client

มาดูสถานการณ์ปกติ:

1. ผู้ใช้คลิกปุ่มเข้าสู่ระบบในเว็บแอปพลิเคชัน

ในเว็บแอปพลิเคชันที่ใช้การเรนเดอร์ฝั่งเซิร์ฟเวอร์แบบดั้งเดิม, ส่วนหน้าและส่วนหลังจะถูกรวมกัน มาลองสมมติกันว่าเว็บแอปพลิเคชันให้บริการทั้งส่วนหน้าและส่วนหลัง:

  • Subject: ผู้ใช้
  • Audience: OIDC เซิร์ฟเวอร์
  • Client: เว็บแอปพลิเคชัน

มันอาจดูขัดแย้งที่ audience เป็น OIDC เซิร์ฟเวอร์ แต่จริงแล้ว มันเป็นกุญแจสำคัญในการตระหนักถึงประสบการณ์ SSO (Single Sign-On) สำหรับผู้ใช้งาน มาดูภาพลำดับแบบย่อสำหรับ authorization code flow:

code เป็นโค้ดที่ใช้ได้ครั้งเดียวที่สามารถเปลี่ยนเป็นโทเค็นต่างๆ เช่น access token, ID token, และ refresh token คุณไม่ต้องกังวลหากคุณยังไม่เข้าใจโทเค็นทั้งหมดนี้ ณ ขณะนี้ เมื่อเราก้าวไปข้างหน้า, คุณจะมีความเข้าใจดีขึ้นเกี่ยวกับมัน

ในกรณีข้างต้น ผู้ใช้ไม่จำเป็นต้องเข้าสู่ระบบอีกครั้งหากพวกเขาสลับไปยังแอปพลิเคชันอื่นเพราะผู้ใช้ (subject) ได้สืบค้นตัวตนกับ OIDC เซิร์ฟเวอร์ (audience) แล้ว

2. ผู้ใช้ใช้งานแอปพลิเคชันหน้าเดียว

ในแอปพลิเคชันหน้าเดียว (หรือแอปพลิเคชันมือถือ), ส่วนหน้าและส่วนหลังถูกแยกจากกัน ลองสมมติว่าด้านหลังเป็นบริการ API:

  • Subject: ผู้ใช้
  • Audience: บริการ API
  • Client: แอปพลิเคชันหน้าเดียว (SPA)

ภาพลำดับแบบย่อกับ authorization code flow:

เนื่องจากบริการ API ไม่โต้ตอบ, SPA จำเป็นต้องใช้ access token กับบริการ API เป็น audience (aud ในโทเค็น)

ทำไม OIDC เซิร์ฟเวอร์ยังเป็น audience?

โดยทางเทคนิคคุณสามารถลบ OIDC เซิร์ฟเวอร์ออกจากรายการ audience แต่อย่างไรก็ตาม ในหลายกรณี, คุณจะต้องการข้อมูลผู้ใช้จาก OIDC เซิร์ฟเวอร์ (ซึ่งต้องการให้ OIDC เซิร์ฟเวอร์เป็น audience) ดังนั้นดีกว่าที่จะรวมถึง OIDC เซิร์ฟเวอร์ในรายการ audience เสมอเมื่อมีการโต้ตอบกับผู้ใช้

เดี๋ยวก่อน, คุณบอกว่าเราสามารถมีหลาย audience ในการร้องขอการให้สิทธิ์ได้หรือ?

ถูกต้อง! จำไว้ว่า OIDC ถูกสร้างบน OAuth 2.0, มันเป็นไปได้ที่จะใช้ RFC 8707: Resource Indicators for OAuth 2.0 ในการร้องขอการให้สิทธิ์เพื่อระบุ audience หลายตัว ซึ่งมันต้องการการสนับสนุนจากทั้ง grant และ OIDC เซิร์ฟเวอร์ ซึ่ง Logto สนับสนุนฟีเจอร์นี้โดยเริ่มต้น

3. การสื่อสารระหว่างเครื่องกับเครื่อง

สมมติว่าคุณมีบริการ A ที่ต้องการเรียกบริการ B:

  • Subject: บริการ A
  • Audience: บริการ B
  • Client: บริการ A

ภาพลำดับแบบย่อกับ client credentials grant:

เมื่อบริการ B ต้องการเรียกใช้บริการ A, บทบาทก็เพียงเปลี่ยนกัน

สรุป

  • Subject: มันสามารถเป็นผู้ใช้, บริการ, หรือหน่วยอื่นๆ ที่ต้องการเข้าถึง audience
  • Client: มันสามารถเป็นแอปพลิเคชันเว็บ, แอปพลิเคชันมือถือ, หรือหน่วยใดๆ ที่เริ่มร้องขอหรือทำการแทน subject
  • Audience: มันสามารถเป็นบริการ, API, หรือหน่วยใดๆ ที่ให้การเข้าถึง subject

โทเค็นการเข้าถึง, ID tokens, และ refresh tokens คืออะไร?

มีสามประเภทของโทเค็นที่คุณอาจพบบ่อยเมื่อทำงานกับ OIDC:

  • Access token: ใช้ในการเข้าถึง audience สามารถเป็น JWT (JSON Web Token) หรือ opaque token (โดยทั่วไปเป็นสตริงสุ่ม)
  • ID token: โทเค็นเฉพาะของ OIDC ที่มีข้อมูลผู้ใช้ มันเป็น JWT เสมอ Client สามารถถอดรหัสโทเค็นเพื่อรับข้อมูลผู้ใช้
  • Refresh token: ใช้ในการรับโทเค็นชุดใหม่เมื่อ access token หรือ ID token หมดอายุ

สำหรับคำอธิบายรายละเอียดของโทเค็นเหล่านี้, คุณสามารถอ้างอิงจาก Understanding refresh tokens, access tokens, and ID tokens in OIDC protocol

ในสถานการณ์ด้านบน 1 และ 2, คำว่า authorization request หมายถึงการร้องขอที่จะรับโทเค็นชุดหนึ่งผ่าน grant ที่เฉพาะเจาะจง

เมื่อทุกอย่างไปได้ดี, โทเค็นชุดหนึ่งจะถูกส่งกลับมาในขั้นตอนไปแลกเปลี่ยนโทเค็นใช้ code โทเค็นที่มีอยู่ในชุดขึ้นอยู่กับหลายปัจจัย, โดยเฉพาะ parameter scope ในการร้องขอการให้สิทธิ์ เพื่อความง่าย, เราจะสมมติว่าโทเค็นทั้งหมดถูกส่งกลับมาในชุด เมื่อ access token หมดอายุ, Client สามารถใช้ refresh token เพื่อรับโทเค็นชุดใหม่ได้โดยไม่ต้องมีการโต้ตอบกับผู้ใช้

สำหรับสถานการณ์ที่ 3, มันง่ายกว่าเพราะ client credentials grant คืนเพียงแค่ access token เท่านั้น

วิธีจัดการหลาย audience ใน OIDC

คุณอาจสังเกตเห็นว่าเพียงแค่ access token ถูกส่งกลับมาครั้งละหนึ่งเดียว ทำอย่างไรเมื่อ client จำเป็นต้องเข้าถึงหลาย audience?

มีสองวิธีที่แพร่หลาย:

ระบุ resource ในคำร้องแลกเปลี่ยนโค้ด

เมื่อ client แลกเปลี่ยนโค้ดเพื่อรับโทเค็น, มันสามารถระบุ parameter resource ในคำร้องได้ OIDC เซิร์ฟเวอร์จะคืน access token สำหรับ audience ที่ระบุหากสามารถทำได้

นี่คือตัวอย่างที่ไม่มีบรรทัดฐาน:

จากนั้น OIDC เซิร์ฟเวอร์จะคืน access token สำหรับ API_SERVICE audience หากสามารถทำได้

ใช้ refresh token เพื่อรับ access token ใหม่

ด้วย RFC 8707, Client สามารถระบุหลาย audience ได้ด้วยการใช้ parameter resource หลายครั้ง ตอนนี้, หาก refresh token มีอยู่ใน client, client อาจระบุ audience ใน parameter resource เมื่อทำการรีเฟรชโทเค็น

นี่คือตัวอย่างที่ไม่มีบรรทัดฐาน:

มันมีผลเช่นเดียวกับวิธีที่ก่อนหน้านี้ ขณะที่ audience อื่นๆ ที่ได้รับอนุญาตยังคงใช้งานได้ในการร้องขอโทเค็นในอนาคต

Client credentials grant

คุณยังสามารถใช้พารามิเตอร์ resource ใน client credentials grant เพื่อระบุ audience ไม่มีปัญหากับหลาย audience ใน grant นี้เนื่องจากคุณสามารถร้องขอ access token ใหม่สำหรับ audience อื่นได้เสมอโดยเพียงแค่ส่งคำร้องทโคเค็นอีกครั้ง

ปกป้องบริการ API ของคุณ

"บริการ API" ในสถานการณ์ที่ 2 และ "บริการ B" ในสถานการณ์ที่ 3 มีสิ่งหนึ่งที่เหมือนกัน: พวกมันต้องตรวจสอบ access token เพื่อระบุว่าคำร้องได้รับอนุญาตหรือไม่ ขึ้นอยู่กับรูปแบบของ access token, กระบวนการตรวจสอบอาจแตกต่างกันไป

  • Opaque token: บริการ API จำเป็นต้องเรียก OIDC เซิร์ฟเวอร์เพื่อทดสอบความถูกต้องของโทเค็น introspection endpoint มักจะมีให้จาก OIDC เซิร์ฟเวอร์สำหรับวัตถุประสงค์นี้
  • JWT: บริการ API สามารถตรวจสอบโทเค็นในท้องถิ่นโดยการตรวจเช็คลายเซ็นและข้อบ่งชี้ในโทเค็น OIDC เซิร์ฟเวอร์มักจะให้บริการ JSON Web Key Set (JWKS) endpoint (jwks_uri) สำหรับบริการ API เพื่อให้ได้รับกุญแจสาธารณะเพื่อตรวจสอบลายเซ็น

หากคุณยังใหม่กับ JWT, คุณสามารถอ้างอิงจาก What is JSON Web Token (JWT)? ในความเป็นจริง, ไม่มีความจำเป็นที่ต้องตรวจสอบลายเซ็นและยืนยันข้อบ่งชี้ด้วยตนเองเนื่องจากมีไลบรารีหลายตัวที่สามารถทำได้ให้คุณ, เช่น jose สำหรับ Node.js และเว็บเบราว์เซอร์

ยืนยันข้อบ่งชี้

นอกเหนือจากการตรวจสอบลายเซ็น JWT, บริการ API ควรตรวจสอบข้อบ่งชี้ในโทเค็นเสมอ:

  • iss: ผู้ให้โทเค็น มันควรตรงกับ URL ผู้ให้บริการของ OIDC
  • aud: audience ของโทเค็น มันควรตรงกับค่า audience ของบริการ API (โดยทั่วไปเป็น URI ที่ถูกต้อง)
  • exp: เวลาหมดอายุของโทเค็น บริการ API ควรปฏิเสธโทเค็นหากมันหมดอายุแล้ว
  • scope: ขอบเขต (สิทธิ์) ของโทเค็น บริการ API ควรตรวจสอบว่ามี scope ที่ต้องการอยู่ในโทเค็น

ข้อบ่งชี้อื่นๆ, เช่น sub (subject) และ iat (issued at), ก็สำคัญในบางกรณี หากคุณมีมาตรการรักษาความปลอดภัยเพิ่มเติม, ตรวจสอบข้อบ่งชี้ตามที่จำเป็น

การอนุญาต

ยังมีคำถามหนึ่งที่ยังไม่ได้ตอบ: เราจะระบุได้อย่างไรว่าจะให้ scope (เช่น สิทธิ์) แก่ subject ได้หรือไม่?

คำถามเดียวนี้นำไปสู่โลกใบใหม่ทั้งหมดของการอนุญาตซึ่งอยู่นอกขอบข่ายของบทความนี้ โดยย่อ, มีวิธีที่แพร่หลายบางวิธีเช่น RBAC (Role-Based Access Control) และ ABAC (Attribute-Based Access Control) นี่คือแหล่งข้อมูลบางอย่างที่จะช่วยให้คุณเริ่มต้น:

สรุป

การนำ OIDC เซิร์ฟเวอร์เข้ามาในโปรเจคของคุณเป็นก้าวใหญ่ มันสามารถปรับปรุงความปลอดภัยและความสามารถในการขยายตัวของโปรเจคของคุณอย่างมาก ทั้งนี้ก็อาจจะใช้เวลาสักหน่อยในการเข้าใจแนวคิดและปฏิสัมพันธ์ระหว่างคอมโพเนนต์

การเลือก OIDC Provider ที่ดีที่เหมาะสมกับความต้องการและความชอบของคุณสามารถลดความซับซ้อนของกระบวนการผนวกรวมอย่างมีนัยสำคัญ เนื่องจากผู้ให้บริการมักจะมีแพ็คเกจที่ครบถ้วน, ซึ่งรวมถึง OIDC เซิร์ฟเวอร์, กลไกการอนุญาต, SDK, และฟีเจอร์ระดับองค์กรที่คุณอาจต้องการในอนาคต

หวังว่าคู่มือนี้จะช่วยให้คุณเข้าใจพื้นฐานของการผนวกรวม OIDC เซิร์ฟเวอร์ หากคุณกำลังมองหาตัวเริ่มต้น, ฉันขอแนะนำ Logto, โครงสร้างพื้นฐานของตัวตนสำหรับนักพัฒนาของเรา