คู่มือสมบูรณ์ในการผนวกรวม OIDC เซิร์ฟเวอร์เข้ากับโปรเจคของคุณ
เรียนรู้แนวปฏิบัติที่ดีที่สุดในการผนวกรวม OIDC (OpenID Connect) เซิร์ฟเวอร์เข้ากับโปรเจคของคุณและทำความเข้าใจว่าคอมโพเนนต์ต่างๆ ทำงานร่วมกันบนเวทีอย่างไร
เรียนรู้แนวปฏิบัติที่ดีที่สุดในการผนวกรวม OIDC (OpenID Connect) เซิร์ฟเวอร์เข้ากับโปรเจคของคุณและทำความเข้าใจว่าคอมโพเนนต์ต่างๆ ทำงานร่วมกันบนเวทีอย่างไร
คุณอาจพบสถานการณ์ที่คุณต้องการระบบการสืบค้นตัวตนและการอนุญาตแบบศูนย์กลาง หรือที่เรียกกันว่า Identity Access Management (IAM) หรือ Identity Provider (IdP) บางครั้งคนจะเพิ่มคำเข้ามาเพื่อระบุธุรกิจ เช่น Customer IAM และ Workforce IAM
มาปล่อยชื่อสุดหรูเหล่านี้ไปสักครู่ ความต้องการในด้าน IAM อาจเกิดขึ้นเพราะแอปพลิเคชันของคุณกำลังเติบโต หรือคุณวางแผนที่จะมอบหมายงานที่ยุ่งยากให้กับผู้ให้บริการตั้งแต่เริ่มต้น อย่างไรก็ตาม คุณกำลังมาถึงจุดที่ระบบตัวตนจะต้องถูกนำเสนอในโปรเจคของคุณ
พิจารณาจากความนิยมของ OAuth 2.0, OpenID Connect (OIDC) จึงเป็นทางเลือกที่เป็นธรรมชาติสำหรับนักพัฒนาหลายๆ คน เนื่องจาก OIDC เป็นเลเยอร์การสืบค้นตัวตนที่ถูกสร้างขึ้นบน OAuth 2.0 คุณอาจรู้สึกคุ้นเคยเมื่อเริ่มทำงานกับ OIDC มากขึ้น มาเริ่มต้นกันเลย!
OIDC เซิร์ฟเวอร์ หรือ Identity Provider เป็นระบบศูนย์กลางที่จัดการความปลอดภัยในการยืนยันตัวตนและการให้สิทธิ์เข้าถึงของผู้ใช้ ตามที่เราได้กล่าวถึงใน ทำไมคุณต้องมีระบบตัวตนแบบศูนย์กลางสำหรับธุรกิจหลายแอป ระบบตัวตนแบบศูนย์กลางมีประโยชน์หลายประการ
สมมติว่าปรเจคของคุณเริ่มต้นด้วยเว็บแอปพลิเคชันที่เรียบง่าย และมีการสืบค้นตัวตนในตัว:
เมื่อปรเจคของคุณเติบโตขึ้น คุณต้องแนะนำเวอร์ชั่นมือถือ:
มันจะเป็นประสบการณ์ที่ไม่ดีสำหรับผู้ใช้หากพวกเขาต้องสร้างบัญชีสำหรับแต่ละแอปพลิเคชัน เนื่องจากคุณเริ่มต้นด้วยเว็บแอปพลิเคชัน คุณให้แอปพลิเคชันมือถือสื่อสารกับเว็บแอปพลิเคชันสำหรับการสืบค้นตัวตน:
ตอนนี้ บริการ API ใหม่กำลังถูกนำเสนอ เนื่องจากเป็นบริการสำหรับผู้ใช้ที่มีการชำระเงิน คุณต้องทำให้แน่ใจว่าผู้ใช้ได้สืบค้นตัวตนและได้รับสิทธิ์เข้าถึงบริการได้อย่างถูกต้อง เพื่อบรรลุเป้าหมายนี้ คุณสามารถสร้างพร็อกซีให้บริการผ่านเว็บแอปพลิเคชัน:
หรือ ใช้เทคนิคโทเค็นบางชนิดในการสืบค้นตัวตนของผู้ใช้ และตรวจสอบความถูกต้องของโทเค็นด้วยการติดต่อกับเว็บแอปพลิเคชันในบริการ ดังนั้นแอปพลิเคชันมือถือสามารถใช้บริการได้โดยตรง:
สิ่งต่างๆ กำลังวุ่นวาย ดังนั้นคุณตัดสินใจที่จะแยกการสืบค้นตัวตนและการให้สิทธิ์เข้าถึงไปเป็นบริการที่แยกออกมา:
กระบวนการรีแฟกเตอร์สามารถเป็นการเจ็บปวด คุณอาจสังเกตเห็นว่าความซับซ้อนของมันจะเพิ่มขึ้นอย่างรวดเร็วเมื่อคุณเพิ่มแอปพลิเคชันและบริการในโปรเจคมากขึ้น ยิ่งแย่ไปกว่านั้น คุณอาจต้องรักษาวิธีการสืบค้นตัวตนหลากหลายรูปแบบ เช่น การเข้าสู่ระบบโดยไม่ใช้รหัสผ่าน, การเข้าสู่ระบบโซเชียล, SAML เป็นต้น
นี่คือเหตุผลว่าทำไมน่าจะดีกว่าหากเราแนะนำ Identity Provider ต้นเมื่อคุณมีแผนที่จะขยายโปรเจคของคุณขึ้น
มี OIDC Provider จำนวนมากในตลาด คุณสามารถเลือกหนึ่งตามความต้องการและความชอบของคุณ ตราบใดที่ผู้ให้บริการสอดคล้องกับ OIDC, มันจะทำบทบาทเดียวกันในโปรเจคของคุณ
เพื่อความง่ายในการทำความเข้าใจแนวคิด, เราสามารถนึกถึง subject เป็นหน่วยที่กำลังร้องขอการเข้าถึง audience ผ่าน client
มาดูสถานการณ์ปกติ:
ในเว็บแอปพลิเคชันที่ใช้การเรนเดอร์ฝั่งเซิร์ฟเวอร์แบบดั้งเดิม, ส่วนหน้าและส่วนหลังจะถูกรวมกัน มาลองสมมติกันว่าเว็บแอปพลิเคชันให้บริการทั้งส่วนหน้าและส่วนหลัง:
มันอาจดูขัดแย้งที่ audience เป็น OIDC เซิร์ฟเวอร์ แต่จริงแล้ว มันเป็นกุญแจสำคัญในการตระหนักถึงประสบการณ์ SSO (Single Sign-On) สำหรับผู้ใช้งาน มาดูภาพลำดับแบบย่อสำหรับ authorization code flow:
code เป็นโค้ดที่ใช้ได้ครั้งเดียวที่สามารถเปลี่ยนเป็นโทเค็นต่างๆ เช่น access token, ID token, และ refresh token คุณไม่ต้องกังวลหากคุณยังไม่เข้าใจโทเค็นทั้งหมดนี้ ณ ขณะนี้ เมื่อเราก้าวไปข้างหน้า, คุณจะมีความเข้าใจดีขึ้นเกี่ยวกับมัน
ในกรณีข้างต้น ผู้ใช้ไม่จำเป็นต้องเข้าสู่ระบบอีกครั้งหากพวกเขาสลับไปยังแอปพลิเคชันอื่นเพราะผู้ใช้ (subject) ได้สืบค้นตัวตนกับ OIDC เซิร์ฟเวอร์ (audience) แล้ว
ในแอปพลิเคชันหน้าเดียว (หรือแอปพลิเคชันมือถือ), ส่วนหน้าและส่วนหลังถูกแยกจากกัน ลองสมมติว่าด้านหลังเป็นบริการ API:
ภาพลำดับแบบย่อกับ 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 สนับสนุนฟีเจอร์นี้โดยเริ่มต้น
สมมติว่าคุณมีบริการ A ที่ต้องการเรียกบริการ B:
ภาพลำดับแบบย่อกับ client credentials grant:
เมื่อบริการ B ต้องการเรียกใช้บริการ A, บทบาทก็เพียงเปลี่ยนกัน
มีสามประเภทของโทเค็นที่คุณอาจพบบ่อยเมื่อทำงานกับ OIDC:
สำหรับคำอธิบายรายละเอียดของโทเค็นเหล่านี้, คุณสามารถอ้างอิงจาก 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 เท่านั้น
คุณอาจสังเกตเห็นว่าเพียงแค่ access token ถูกส่งกลับมาครั้งละหนึ่งเดียว ทำอย่างไรเมื่อ client จำเป็นต้องเข้าถึงหลาย audience?
มีสองวิธีที่แพร่หลาย:
resource ในคำร้องแลกเปลี่ยนโค้ดเมื่อ client แลกเปลี่ยนโค้ดเพื่อรับโทเค็น, มันสามารถระบุ parameter resource ในคำร้องได้ OIDC เซิร์ฟเวอร์จะคืน access token สำหรับ audience ที่ระบุหากสามารถทำได้
นี่คือตัวอย่างที่ไม่มีบรรทัดฐาน:
จากนั้น OIDC เซิร์ฟเวอร์จะคืน access token สำหรับ API_SERVICE audience หากสามารถทำได้
ด้วย RFC 8707, Client สามารถระบุหลาย audience ได้ด้วยการใช้ parameter resource หลายครั้ง ตอนนี้, หาก refresh token มีอยู่ใน client, client อาจระบุ audience ใน parameter resource เมื่อทำการรีเฟรชโทเค็น
นี่คือตัวอย่างที่ไม่มีบรรทัดฐาน:
มันมีผลเช่นเดียวกับวิธีที่ก่อนหน้านี้ ขณะที่ audience อื่นๆ ที่ได้รับอนุญาตยังคงใช้งานได้ในการร้องขอโทเค็นในอนาคต
คุณยังสามารถใช้พารามิเตอร์ resource ใน client credentials grant เพื่อระบุ audience ไม่มีปัญหากับหลาย audience ใน grant นี้เนื่องจากคุณสามารถร้องขอ access token ใหม่สำหรับ audience อื่นได้เสมอโดยเพียงแค่ส่งคำร้องทโคเค็นอีกครั้ง
"บริการ API" ในสถานการณ์ที่ 2 และ "บริการ B" ในสถานการณ์ที่ 3 มีสิ่งหนึ่งที่เหมือนกัน: พวกมันต้องตรวจสอบ access token เพื่อระบุว่าคำร้องได้รับอนุญาตหรือไม่ ขึ้นอยู่กับรูปแบบของ access token, กระบวนการตรวจสอบอาจแตกต่างกันไป
jwks_uri) สำหรับบริการ API เพื่อให้ได้รับกุญแจสาธารณะเพื่อตรวจสอบลายเซ็นหากคุณยังใหม่กับ JWT, คุณสามารถอ้างอิงจาก What is JSON Web Token (JWT)? ในความเป็นจริง, ไม่มีความจำเป็นที่ต้องตรวจสอบลายเซ็นและยืนยันข้อบ่งชี้ด้วยตนเองเนื่องจากมีไลบรารีหลายตัวที่สามารถทำได้ให้คุณ, เช่น jose สำหรับ Node.js และเว็บเบราว์เซอร์
นอกเหนือจากการตรวจสอบลายเซ็น JWT, บริการ API ควรตรวจสอบข้อบ่งชี้ในโทเค็นเสมอ:
iss: ผู้ให้โทเค็น มันควรตรงกับ URL ผู้ให้บริการของ OIDCaud: 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, โครงสร้างพื้นฐานของตัวตนสำหรับนักพัฒนาของเรา