ตรวจสอบลายเซ็นใน JWT จาก login.microsoftonline.com ด้วย PHP

ฉันกำลังพยายามตั้งค่าบริการการลงชื่อเพียงครั้งเดียวสำหรับหน้าเว็บโดยใช้ บริการ Azure Active Directory / OpenID Connect จาก Microsoft

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

หากต้องการรับโทเค็น ฉันแค่ใช้ลิงก์:

https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=[myclientid]&response_type=id_token&redirect_uri=https://localhost/ssotest.php&response_mode=form_post&scope=openid+profile&state=12345&nonce=678910

(สำหรับผู้ที่พยายามอ่านแบบเดียวกัน ฉันใช้เวลานานกว่าจะค้นพบ แต่คุณสามารถตั้งค่ารหัสลูกค้าของคุณได้ที่นี่: https://apps.dev.microsoft.com/)

จากนั้นหน้านั้นจะโพสต์ข้อมูลไปยังสคริปต์ของฉัน ซึ่งมีลักษณะดังนี้:

array(3) {
  ["id_token"]=>
  string(1026) "abc.def.geh"
  ["state"]=>
  string(5) "12345"
  ["session_state"]=>
  string(36) "dd7781aa-74e8-4aa8-ac7e-d3800c5c2247"
}

จากจุดนั้น ฉันแบ่งโทเค็น ID ออกเป็นส่วนหัว เนื้อหา และลายเซ็น ตามช่วงเวลา/จุดสิ้นสุด

จากนั้นฉันสามารถ base64decode ส่วนหัวได้:

["typ"]=> string(3) "JWT"
["alg"]=> string(5) "RS256"
["kid"]=> string(27) "MnC_VZcATfM5pOYiJHMba9goEKY" 

และร่างกาย:

["aud"]=> string(36) "[client_id]"
["iss"]=> string(75) "https://login.microsoftonline.com/52f161e7.../v2.0"
["iat"]=> int(1466523280)
["nbf"]=> int(1466523280)
["exp"]=> int(1466527180)
["ipaddr"]=> string(15) "111.111.111.111"
["name"]=> string(12) "Mr E Xample"
["nonce"]=> string(6) "678910"
["oid"]=> string(36) "c3beeb42..."
["preferred_username"]=> string(23) "[email protected]"
["sub"]=> string(43) "oGAnGQ..."
["tid"]=> string(36) "52f161e7..."
["ver"]=> string(3) "2.0"

ตอนนี้ฉันมีลายเซ็นแล้ว แต่ฉันไม่แน่ใจจริงๆว่าต้องทำอย่างไร ฉันเข้าใจว่าสามารถรับใบรับรองสาธารณะที่ถูกต้องได้จาก https://login.microsoftonline.com/common/discovery/v2.0/keys ตามที่ระบุโดย kid ในส่วนหัว แต่ฉันไม่แน่ใจว่าจะช่วยได้อย่างไร อย่างที่ฉันรู้กุญแจสาธารณะ ฉันเดาว่าฉันต้องถอดรหัสลายเซ็นด้วยมัน ใช่ไหม??

แน่นอนจะต้องมีวิธีส่งคำขอเซิร์ฟเวอร์ไปยังเซิร์ฟเวอร์เพื่อตรวจสอบข้อมูลที่ส่งถึงฉันจากไคลเอนต์? เช่น. GET https://login.microsoftonline.com/verfifytoken/[token]

ฉันตั้งค่า Google SSO ซึ่งถือว่าง่ายมากเมื่อเทียบกับสิ่งนี้ - ฉันแน่ใจว่าฉันขาดอะไรบางอย่างไป แต่มันดูซับซ้อนเกินไปจริงๆ!

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


person Ben    schedule 21.06.2016    source แหล่งที่มา
comment
จากประสบการณ์ของฉัน เราสามารถใช้ [การอนุญาต: id_token] ในส่วนหัวของคุณได้ และคุณสามารถขอ URL ของแอปของคุณ (คุณลงทะเบียนแอปโดยใช้ URL ) ด้วยส่วนหัวนี้   -  person Will Shao - MSFT    schedule 28.06.2016
comment
ฉันคิดว่าคุณไม่ได้หมายถึงการอนุญาต: id_token แต่การอนุญาต: ผู้ถือ [id_token]?   -  person Konstantin    schedule 25.08.2016
comment
สิ่งนี้อาจช่วยได้   -  person spottedmahn    schedule 10.08.2017


คำตอบ (1)


อย่างที่ฉันรู้กุญแจสาธารณะ ฉันเดาว่าฉันต้องถอดรหัสลายเซ็นด้วยมัน ใช่ไหม??

จริงๆ แล้วสิ่งที่คุณต้องทำคือตรวจสอบลายเซ็นด้วยตัวเอง

คุณสมบัติ alg บอกคุณว่าอัลกอริทึมคือ RS256 ซึ่งหมายถึง RSA 256 ฉันไม่ใช่คน Python แต่การค้นหาอย่างรวดเร็วชี้ให้ฉัน ที่นี่ (ไม่แน่ใจว่าไลบรารีนี้ดีที่สุดหรือไม่...) ซึ่งคุณสามารถตรวจสอบลายเซ็นได้ ข้อความคือสองบล็อกแรกของ JWT (โดยแยกด้วย '.') และลายเซ็นคือบล็อกที่สาม

person Bruno Brant    schedule 15.05.2020