OpenID Connect: การอนุญาตแอปพลิเคชันภายในจากกำหนดเองเป็นมาตรฐาน

ไม่กี่เดือนที่ผ่านมา ฉันใช้เซิร์ฟเวอร์ OpenID Connect เพื่อจัดการการเข้าถึงแอปพลิเคชันภายในหลายร้อยรายการของเรา จากการพัฒนาของเราเอง อำนวยความสะดวกในขนาดที่เล็กลง เราได้ก้าวไปสู่มาตรฐานที่ยอมรับโดยทั่วไป การเข้าถึงผ่านบริการส่วนกลางช่วยลดความยุ่งยากในการทำงานที่ซ้ำซากจำเจ ลดค่าใช้จ่ายในการดำเนินการอนุญาต ช่วยให้คุณค้นหาโซลูชันสำเร็จรูปมากมายและไม่ต้องเปลืองสมองเมื่อพัฒนาโซลูชันใหม่ ในบทความนี้ ฉันจะพูดถึงการเปลี่ยนแปลงนี้และการกระแทกที่เราจัดการเพื่อเติมเต็ม

OpenID Connect: การอนุญาตแอปพลิเคชันภายในจากกำหนดเองเป็นมาตรฐาน

นานมาแล้ว... มันเริ่มต้นอย่างไร

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

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

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

ตามมาตรฐานทั่วไป

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

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

OpenID Connect: การอนุญาตแอปพลิเคชันภายในจากกำหนดเองเป็นมาตรฐาน

วิธีของเราในการปรับใช้เซิร์ฟเวอร์ OIDC ของเราเอง

1) นำข้อมูลมาสู่แบบฟอร์มที่ต้องการ

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

กลุ่มของตราสัญลักษณ์จะรวมกันเป็นส่วนย่อยต่อไปนี้ - ขอบเขต ในระหว่างการให้สิทธิ์ การเข้าถึงจะไม่ถูกร้องขอเฉพาะแบรนด์ แต่ให้เข้าถึงขอบเขต แม้ว่าบางแบรนด์จากขอบเขตจะไม่จำเป็นก็ตาม

2) ดำเนินการตามทุนที่จำเป็น

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

OpenID Connect: การอนุญาตแอปพลิเคชันภายในจากกำหนดเองเป็นมาตรฐาน

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

OAuth ยึดตามแนวคิดที่ว่าโทเค็นการเข้าถึงที่ได้รับหลังจากการให้สิทธิ์ควรเป็นแบบชั่วคราวและควรเปลี่ยนแปลงโดยเฉลี่ยทุกๆ 10 นาที การให้รหัสอนุญาตเป็นการตรวจสอบสามขั้นตอนผ่านการเปลี่ยนเส้นทาง ทุก ๆ 10 นาทีเพื่อเปลี่ยนขั้นตอนดังกล่าว ตรงไปตรงมา ไม่ใช่งานที่น่าพอใจที่สุดสำหรับสายตา เพื่อแก้ปัญหานี้มีการอนุญาตอื่น - Refresh Token ซึ่งเราใช้ในประเทศของเราด้วย ทุกอย่างง่ายขึ้นที่นี่ ในระหว่างการตรวจสอบจากการอนุญาตอื่น นอกจากโทเค็นการเข้าถึงหลักแล้ว ยังมีการออกโทเค็นใหม่อีกอันหนึ่ง นั่นคือ รีเฟรชโทเค็น ซึ่งสามารถใช้ได้เพียงครั้งเดียวและอายุการใช้งานมักจะยาวนานกว่านั้นมาก ด้วยโทเค็นการรีเฟรชนี้ เมื่อ TTL (Time to Live) ของโทเค็นการเข้าถึงหลักสิ้นสุดลง คำขอสำหรับโทเค็นการเข้าถึงใหม่จะมาถึงจุดสิ้นสุดของการอนุญาตอื่น โทเค็นการรีเฟรชที่ใช้จะถูกรีเซ็ตเป็นศูนย์ทันที การตรวจสอบนี้มีสองขั้นตอนและสามารถดำเนินการในพื้นหลังโดยที่ผู้ใช้มองไม่เห็น

3) ตั้งค่ารูปแบบเอาต์พุตข้อมูลแบบกำหนดเอง

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

ในการใช้งาน OIDC โทเค็น JWT เรียกว่า id_token สามารถขอได้พร้อมกับโทเค็นการเข้าถึงปกติ ที่เหลือคือการตรวจสอบลายเซ็น เซิร์ฟเวอร์การอนุญาตมีจุดสิ้นสุดแยกต่างหากสำหรับสิ่งนี้ด้วยคีย์สาธารณะจำนวนมากในรูปแบบ JWK. และเมื่อพูดถึงสิ่งนี้ มันก็คุ้มค่าที่จะกล่าวถึงว่ามีจุดสิ้นสุดอีกจุดหนึ่งซึ่งอิงตามมาตรฐาน RFC5785 สะท้อนการกำหนดค่าปัจจุบันของเซิร์ฟเวอร์ OIDC ประกอบด้วยที่อยู่ปลายทางทั้งหมด (รวมถึงที่อยู่ของคีย์ริงสาธารณะที่ใช้สำหรับการเซ็นชื่อ) แบรนด์และขอบเขตที่รองรับ อัลกอริทึมการเข้ารหัสที่ใช้ ทุนสนับสนุน ฯลฯ

ตัวอย่างเช่นใน Google:

{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}

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

ผลการดำเนินการ

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

พูดคุยเกี่ยวกับโซลูชันที่มีอยู่

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

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

Keycloak และ Ory Hydra ไม่ใช่โซลูชันที่หาซื้อได้ตามร้านค้าทั่วไป เป็นการดีที่สุดที่จะเลือกการใช้งานที่รับรองโดย OpenID Foundation โซลูชันเหล่านี้มักจะมีตรารับรอง OpenID

OpenID Connect: การอนุญาตแอปพลิเคชันภายในจากกำหนดเองเป็นมาตรฐาน

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

มีอะไรต่อไป

ในอนาคตอันใกล้นี้ เราจะปิดการรับส่งข้อมูลไปยังบริการภายในด้วยวิธีอื่น เราวางแผนที่จะโอน SSO ปัจจุบันของเราบนบาลานเซอร์โดยใช้ OpenResty ไปยังพร็อกซีตาม OAuth มีโซลูชันสำเร็จรูปมากมายที่นี่ เช่น:
github.com/bitly/oauth2_proxy
github.com/ory/othkeeper
github.com/keycloak/keycloak-gatekeeper

วัสดุเพิ่มเติม

jwt.io – บริการที่ดีสำหรับการตรวจสอบโทเค็น JWT
openid.net/developers/ได้รับการรับรอง - รายชื่อการใช้งาน OIDC ที่ได้รับการรับรอง

ที่มา: will.com

เพิ่มความคิดเห็น