ภาพรวมของนโยบาย JWS และ JWT

คุณกำลังดูเอกสารประกอบของ Apigee Edge
ไปที่ เอกสารประกอบของ Apigee X
info

หัวข้อนี้ให้ข้อมูลทั่วไปเกี่ยวกับ JWT (JSON Web Token) และ JWS (JSON Web Signature) รวมถึงนโยบาย JWS/JWT ของ Apigee ที่อาจเป็นประโยชน์ต่อนักพัฒนาพร็อกซี Apigee

บทนำ

ทั้ง JWS และ JWT ใช้กันโดยทั่วไปเพื่อแชร์การอ้างสิทธิ์หรือการยืนยันระหว่างแอปพลิเคชันที่เชื่อมต่อ นโยบาย JWS/JWT ช่วยให้พร็อกซี API ของ Edge ทำสิ่งต่อไปนี้ได้

  • สร้าง JWT หรือ JWS ที่ลงชื่อแล้ว
  • ยืนยัน JWT หรือ JWS ที่ลงชื่อแล้วและการอ้างสิทธิ์ภายใน JWS/JWT
  • ถอดรหัส JWT หรือ JWS ที่ลงชื่อแล้วโดยไม่ต้องตรวจสอบลายเซ็น

ใน 2 กรณีหลัง นโยบายยังตั้งค่าตัวแปรที่อนุญาตให้นโยบายเพิ่มเติมหรือบริการแบ็กเอนด์เองตรวจสอบการอ้างสิทธิ์ที่ตรวจสอบแล้วและตัดสินใจตามการอ้างสิทธิ์เหล่านั้น

เมื่อใช้นโยบาย Verify JWS/JWT ระบบจะปฏิเสธ JWS/JWT ที่ไม่ถูกต้องและทำให้เกิดเงื่อนไขข้อผิดพลาด ในทำนองเดียวกัน เมื่อใช้นโยบาย Decode JWS/JWT ระบบจะทำให้เกิดเงื่อนไขข้อผิดพลาด หาก JWS/JWT มีรูปแบบไม่ถูกต้อง

วิดีโอ

ดูวิดีโอสั้นๆ เพื่อดูข้อมูลเบื้องต้นเกี่ยวกับ JWT แม้ว่าวิดีโอนี้จะ เจาะจงไปที่การสร้าง JWT แต่แนวคิดหลายอย่างก็เหมือนกับ JWS

ดูวิดีโอสั้นๆ เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับโครงสร้าง JWT

กรณีการใช้งาน

คุณสามารถใช้นโยบาย JWS/JWT เพื่อทำสิ่งต่อไปนี้

  • สร้าง JWS/JWT ใหม่ที่ด้านพร็อกซีหรือปลายทางเป้าหมายของพร็อกซี Edge เช่น คุณอาจสร้างโฟลว์คำขอพร็อกซีที่สร้าง JWS/JWT และส่งกลับไปยังไคลเอ็นต์ หรือคุณอาจออกแบบพร็อกซีเพื่อให้สร้าง JWS/JWT ในโฟลว์คำขอเป้าหมายและ แนบ JWS/JWT กับคำขอที่ส่งไปยังเป้าหมาย จากนั้นการอ้างสิทธิ์เหล่านั้นจะพร้อมใช้งานเพื่อให้บริการ แบ็กเอนด์ใช้การประมวลผลด้านความปลอดภัยเพิ่มเติมได้
  • ยืนยันและแยกการอ้างสิทธิ์จาก JWS/JWT ที่ได้รับจากคำขอของไคลเอ็นต์ขาเข้า, การตอบกลับของบริการเป้าหมาย การตอบกลับของนโยบาย Service Callout หรือจากแหล่งที่มาอื่นๆ Edge จะ ยืนยันลายเซ็นใน JWS/JWT ไม่ว่า JWS/JWT จะสร้างขึ้นโดยบุคคลที่สามหรือโดย Edge เอง โดยใช้อัลกอริทึม RSA หรือ HMAC
  • ถอดรหัส JWS/JWT การถอดรหัสจะมีประโยชน์มากที่สุดเมื่อใช้ร่วมกับนโยบาย Verify JWS/JWT ในกรณีที่ต้องทราบค่าของการอ้างสิทธิ์ (JWT) หรือส่วนหัว (JWS/JWT) จากภายใน JWS/JWT ก่อนที่จะยืนยัน JWS/JWT

ส่วนต่างๆ ของ JWS/JWT

JWS/JWT ที่ลงชื่อแล้วจะเข้ารหัสข้อมูลเป็น 3 ส่วนที่คั่นด้วยจุด ได้แก่ ส่วนหัว เพย์โหลด และ ลายเซ็น

header.payload.signature
  • นโยบาย Generate JWS/JWT จะสร้างทั้ง 3 ส่วน
  • นโยบาย Verify JWS/JWT จะตรวจสอบทั้ง 3 ส่วน
  • นโยบาย Decode JWS/JWT จะตรวจสอบเฉพาะส่วนหัวและเพย์โหลด

นอกจากนี้ JWS ยังรองรับรูปแบบ แยก ซึ่งละเว้นเพย์โหลดจาก JWS

header..signature

ใน JWS ที่แยก เพย์โหลดจะถูกส่งแยกจาก JWS คุณใช้ <DetachedContent> องค์ประกอบของนโยบาย Verify JWS เพื่อระบุเพย์โหลด JWS ดิบที่ไม่ได้เข้ารหัส จากนั้นนโยบาย Verify JWS จะยืนยัน JWS โดยใช้ส่วนหัวและลายเซ็นใน JWS รวมถึงเพย์โหลด ที่ระบุโดยองค์ประกอบ <DetachedContent>

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

ความแตกต่างระหว่าง JWS กับ JWT

คุณสามารถใช้ JWT หรือ JWS เพื่อแชร์การอ้างสิทธิ์หรือการยืนยันระหว่างแอปพลิเคชันที่เชื่อมต่อ ความแตกต่างที่สำคัญระหว่าง JWT กับ JWS คือการแสดงเพย์โหลด ดังนี้

  • JWT
    • เพย์โหลดจะเป็นออบเจ็กต์ JSON เสมอ
    • เพย์โหลดจะแนบกับ JWT เสมอ
    • ระบบจะตั้งค่าส่วนหัว typ ของโทเค็นเป็น JWT เสมอ
  • JWS
    • เพย์โหลดสามารถแสดงได้ในรูปแบบใดก็ได้ เช่น ออบเจ็กต์ JSON, สตรีมไบต์, สตรีมออกเต็ต และอื่นๆ
    • เพย์โหลดไม่จำเป็นต้องแนบกับ JWS

เนื่องจากรูปแบบ JWT ใช้เฉพาะออบเจ็กต์ JSON เพื่อแสดงเพย์โหลด นโยบาย Generate JWT และ Verify JWT ของ Edge จึงมีการรองรับในตัวเพื่อจัดการชื่อการอ้างสิทธิ์ที่ลงทะเบียนไว้ทั่วไป เช่น aud, iss, sub และอื่นๆ ซึ่งหมายความว่าคุณสามารถใช้องค์ประกอบของ นโยบาย Generate JWT เพื่อตั้งค่าการอ้างสิทธิ์เหล่านี้ในเพย์โหลด และใช้องค์ประกอบของนโยบาย Verify JWT เพื่อยืนยันค่าของการอ้างสิทธิ์ ดูข้อมูลเพิ่มเติมได้ที่ส่วนชื่อการอ้างสิทธิ์ที่ลงทะเบียนไว้ ของข้อกำหนด JWT

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

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

ป้องกันการแทรกเทมเพลตเมื่อใช้ JWS และ JWT

หากต้องการป้องกันการเปิดเผยข้อมูลโดยไม่ได้รับอนุญาต ให้ทำตามหลักเกณฑ์ต่อไปนี้เมื่อใช้นโยบาย GenerateJWT หรือ GenerateJWS

  • หลีกเลี่ยงการอ้างอิงข้อมูลจากผู้ใช้โดยตรง: อย่าใช้ข้อมูลที่ไม่น่าเชื่อถือ (เช่น request.queryparam.* หรือ request.header.*) โดยตรงในแอตทริบิวต์ ref ที่รองรับการใช้เทมเพลต
  • ล้างข้อมูลอินพุต: หากต้องใช้ข้อมูลภายนอกในการอ้างสิทธิ์ JWT/JWS ให้ใช้ นโยบาย AssignMessage เพื่อนำวงเล็บปีกกา ({ }) หรืออักขระเทมเพลตอื่นๆ ออกจากอินพุต ก่อนที่จะอ้างอิง
  • ใช้การอ้างสิทธิ์ที่ชัดเจนสำหรับสตริง: สำหรับการอ้างสิทธิ์สตริงอย่างง่าย ให้หลีกเลี่ยง type="map". การใช้ค่าเริ่มต้น type="string" จะป้องกันการใช้เทมเพลตโดยนัย ของค่าที่อ้างอิง
  • โปรดทราบถึงความไม่สอดคล้องกันของลักษณะการทำงานระหว่างนโยบายการยืนยันและนโยบายการสร้าง: นโยบายการสร้าง JWS และ JWT มีลักษณะการทำงานที่แตกต่างจากนโยบายการยืนยันเกี่ยวกับการใช้เทมเพลต

เกี่ยวกับอัลกอริทึมลายเซ็น

นโยบายการยืนยัน JWS/JWT และนโยบายการสร้าง JWS/JWT รองรับอัลกอริทึม RSA, RSASSA-PSS, ECDSA และ HMAC โดยใช้ผลรวมตรวจสอบ SHA2 ที่มีความแรงของบิต 256, 384 หรือ 512 นโยบายการถอดรหัส JWS/JWT จะทำงานโดยไม่คำนึงถึง อัลกอริทึมที่ใช้ลงชื่อ JWS/JWT

อัลกอริทึม HMAC

อัลกอริทึม HMAC อาศัยข้อมูลลับที่ใช้ร่วมกัน ซึ่งเรียกว่าคีย์ลับ ในการสร้าง ลายเซ็น (หรือที่เรียกว่าการลงชื่อ JWS/JWT) และในการยืนยันลายเซ็น

ความยาวขั้นต่ำของคีย์ลับจะขึ้นอยู่กับความแรงของบิตของอัลกอริทึม ดังนี้

  • HS256: ความยาวคีย์ขั้นต่ำ 32 ไบต์
  • HS386: ความยาวคีย์ขั้นต่ำ 48 ไบต์
  • HS512: ความยาวคีย์ขั้นต่ำ 64 ไบต์

อัลกอริทึม RSA

อัลกอริทึม RSA ใช้คู่คีย์สาธารณะ/ส่วนตัวสำหรับลายเซ็นการเข้ารหัส เมื่อใช้ลายเซ็น RSA ฝ่ายลงชื่อจะใช้คีย์ส่วนตัว RSA เพื่อลงชื่อ JWS/JWT และฝ่ายยืนยันจะใช้ คีย์สาธารณะ RSA ที่ตรงกันเพื่อยืนยันลายเซ็นใน JWS/JWT ไม่มีข้อกำหนดด้านขนาดสำหรับ คีย์

อัลกอริทึม RSASSA-PSS

อัลกอริทึม RSASSA-PSS เป็นอัลกอริทึม RSA ที่อัปเดต เช่นเดียวกับ RSS อัลกอริทึม RSASSA-PSS ใช้คู่คีย์สาธารณะ/ส่วนตัว RSA สำหรับลายเซ็นการเข้ารหัส รูปแบบของคีย์จะเหมือนกับ RSS ฝ่ายลงชื่อจะใช้คีย์ส่วนตัวเพื่อลงชื่อ JWS/JWT และฝ่ายยืนยันจะใช้คีย์สาธารณะที่ตรงกัน เพื่อยืนยันลายเซ็นใน JWS/JWT ไม่มีข้อกำหนดด้านขนาดสำหรับคีย์

อัลกอริทึม ECDSA

อัลกอริทึม Elliptic Curve Digital Signature Algorithm (ECDSA) เป็นอัลกอริทึมการเข้ารหัสเส้นโค้งวงรี ที่มีเส้นโค้ง P-256, P-384 และ P-521 เมื่อใช้อัลกอริทึม ECDSA อัลกอริทึมจะกำหนด ประเภทคีย์สาธารณะและคีย์ส่วนตัวที่คุณต้องระบุ

อัลกอริทึม เส้นโค้ง ข้อกำหนดที่สำคัญ
ES256 P-256 คีย์ที่สร้างจากเส้นโค้ง P-256 (หรือที่เรียกว่า secp256r1 หรือ prime256v1)
ES384 P-384 คีย์ที่สร้างจากเส้นโค้ง P-384 (หรือที่เรียกว่า secp384r1)
ES512 P-521 คีย์ที่สร้างจากเส้นโค้ง P-521 (หรือที่เรียกว่า secp521r1)

อัลกอริทึมการเข้ารหัสคีย์

นโยบาย JWS/JWT รองรับอัลกอริทึมการเข้ารหัสคีย์ทั้งหมดที่ OpenSSL รองรับ

การใช้ JSON Web Key Set (JWKS) เพื่อยืนยัน JWS/JWT

เมื่อยืนยัน JWS/JWT ที่ลงชื่อแล้ว คุณต้องระบุคีย์สาธารณะที่ เชื่อมโยงกับคีย์ส่วนตัวที่ใช้ลงชื่อโทเค็น คุณมีตัวเลือก 2 รายการ ในการ ระบุคีย์สาธารณะสำหรับนโยบายการยืนยัน JWS/JWT ดังนี้

  • ใช้ค่าคีย์สาธารณะจริง (โดยปกติจะระบุไว้ในตัวแปรโฟลว์) หรือ
  • ใช้คีย์สาธารณะที่ห่อหุ้มไว้ใน JWKS

เกี่ยวกับ JWKS

JWKS เป็นโครงสร้าง JSON ที่แสดงชุด JSON Web Key (JWK) JWK เป็นโครงสร้างข้อมูล JSON ที่แสดงคีย์การเข้ารหัส JWK และ JWKS อธิบายไว้ใน RFC7517 ดูตัวอย่าง JKWS ได้ที่ ภาคผนวก ก ตัวอย่าง JSON Web Key Set

โครงสร้าง JWKS

RFC7517 อธิบายองค์ประกอบคีย์ JWKS สำหรับคีย์แต่ละประเภท เช่น "RSA" หรือ "EC" ตัวอย่างเช่น ทั้งนี้ขึ้นอยู่กับประเภทคีย์ พารามิเตอร์เหล่านี้อาจรวมถึงสิ่งต่อไปนี้

  • kty - ประเภทคีย์ เช่น "RSA" หรือ "EC"
  • kid (รหัสคีย์) - อาจเป็นค่าที่กำหนดเอง (ไม่ซ้ำกันภายในชุดคีย์ ) หาก JWT ขาเข้ามีรหัสคีย์ที่อยู่ในชุด JWKS นโยบาย จะใช้คีย์สาธารณะที่ถูกต้องเพื่อยืนยันลายเซ็น JWS/JWT

ตัวอย่างองค์ประกอบที่ไม่บังคับและค่าขององค์ประกอบดังกล่าว

  • alg - อัลกอริทึมคีย์ ต้องตรงกับอัลกอริทึมการลงชื่อใน JWS/JWT
  • use - หากมี ต้องเป็น sig

JWKS ต่อไปนี้มีองค์ประกอบและค่าที่จำเป็น และจะถูกต้องใน Edge (จาก https://www.googleapis.com/oauth2/v3/certs)

{
   "keys":[
      {
         "kty":"RSA",
         "alg":"RS256",
         "use":"sig",
         "kid":"ca04df587b5a7cead80abee9ea8dcf7586a78e01",
         "n":"iXn-WmrwLLBa-QDiToBozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt7-V7KDjCq0_Nkd-X9rMRV5LKgCa0_F8YgI30QS3bUm9orFryrdOc65PUIVFVxIwMZuGDY1hj6HEJVWIr0CZdcgNIll06BasclckkUK4O-Eh7MaQrqb646ghFlG3zlgk9b2duHbDOq3s39ICPinRQWC6NqTYfqg7E8GN_NLY9srUCc_MswuUfMJ2cKT6edrhLuIwIj_74YGkpOwilr2VswKsvJ7dcoiJxheKYvKDKtZFkbKrWETTJSGX2Xeh0DFB0lqbKLVvqkM2lFU2Qx1OgtTnrw",
         "e":"AQAB"
      },
      {
          "kty":"EC",
          "alg":"ES256",
          "use":"enc",
          "kid":"k05TUSt7-V7KDjCq0_N"
          "crv":"P-256",
          "x":"Xej56MungXuFZwmk_xccvsMpCtXmqhvEEMCmHyAmKF0",
          "y":"Bozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt",
      }
   ]
}

การออกแบบพร็อกซีให้ ใช้ JWKS

เมื่อได้รับ JWS/JWT จากผู้ออก ผู้ออกมักจะแทรกรหัสคีย์ (หรือ kid) ลงในส่วนหัว JWS/JWT คีย์จะบอกผู้รับ JWS/JWT ถึงวิธีค้นหาคีย์สาธารณะหรือคีย์ลับที่จำเป็นในการ ยืนยันลายเซ็นใน JWS/JWT ที่ลงชื่อแล้ว

ตัวอย่างเช่น สมมติว่าผู้ออกลงชื่อ JWT ด้วยคีย์ส่วนตัว "รหัสคีย์" จะระบุคีย์สาธารณะที่ตรงกัน เพื่อใช้ยืนยัน JWT โดยปกติแล้วรายการคีย์สาธารณะจะพร้อมใช้งานที่ ปลายทางที่รู้จักกันดี เช่น https://www.googleapis.com/oauth2/v3/certs

นี่คือลำดับพื้นฐานที่ Edge (หรือแพลตฟอร์มใดก็ตามที่ทำงานร่วมกับ JWKS) ต้องดำเนินการ เพื่อทำงานร่วมกับ JWS/JWT ที่มี JWKS

  1. ตรวจสอบส่วนหัว JWS/JWT เพื่อหารหัสคีย์ (kid)
  2. ตรวจสอบส่วนหัว JWS/JWT เพื่อค้นหาอัลกอริทึมการลงชื่อ (alg) เช่น RS256
  3. ดึงรายการคีย์และรหัสจาก JWKS ของปลายทางที่รู้จักกันดีสำหรับผู้ออกที่ระบุ
  4. แยกคีย์สาธารณะจากรายการคีย์ที่มีรหัสคีย์ที่ระบุไว้ในส่วนหัว JWS/JWT และมีอัลกอริทึมที่ตรงกัน หากคีย์ JWKS ระบุอัลกอริทึม
  5. ใช้คีย์สาธารณะนั้นเพื่อยืนยันลายเซ็นใน JWS/JWT

ในฐานะนักพัฒนาพร็อกซี API ของ Edge คุณต้องทำสิ่งต่อไปนี้เพื่อยืนยัน JWS/JWT

  1. ดึงรายการคีย์และรหัสจากปลายทางที่รู้จักกันดีสำหรับผู้ออกที่ระบุ คุณสามารถ ใช้นโยบาย Service Callout สำหรับขั้นตอนนี้ได้
  2. ในนโยบาย Verify JWS/JWT ให้ระบุตำแหน่งของ JWS/JWT ในองค์ประกอบ <Source> และเพย์โหลด JWKS ในองค์ประกอบ <PublicKey/JWKS> ตัวอย่างเช่น สำหรับนโยบาย VerifyJWT
    <VerifyJWT name="JWT-Verify-RS256">
        <Algorithm>RS256</Algorithm>
        <Source>json.jwt</Source>
        <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
        <PublicKey>
            <JWKS ref="public.jwks"/>
        </PublicKey>
        <Subject>apigee-seattle-hatrack-montage</Subject>
        <Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
        <Audience>urn://c60511c0-12a2-473c-80fd-42528eb65a6a</Audience>
        <AdditionalClaims>
            <Claim name="show">And now for something completely different.</Claim>
        </AdditionalClaims>
    </VerifyJWT>

นโยบาย Verify JWT จะดำเนินการอื่นๆ ทั้งหมด ดังนี้

  • หากไม่พบคีย์ที่มีรหัสคีย์ที่ตรงกับรหัสคีย์ (kid) ที่ยืนยันใน JWT ใน JWKS นโยบาย Verify JWT จะแสดงข้อผิดพลาดและไม่ตรวจสอบ JWT
  • หาก JWT ขาเข้าไม่มีรหัสคีย์ (kid) ในส่วนหัว การแมปรหัสคีย์กับคีย์การยืนยันนี้จะเป็นไปไม่ได้

ในฐานะผู้ออกแบบพร็อกซี คุณมีหน้าที่รับผิดชอบในการกำหนดคีย์ที่จะใช้ ซึ่งในบางกรณีนี้ อาจเป็นคีย์ที่คงที่และฮาร์ดโค้ด