• oauth
  • jwt
  • api
  • security
  • authentication
  • authorization
  • machine-to-machine

รักษาความปลอดภัยทรัพยากร API ของคุณสำหรับการสื่อสารระหว่างเครื่องกับเครื่อง

เรียนรู้วิธีใช้ประโยชน์จาก OAuth 2.0 และ JWT เพื่อรักษาความปลอดภัยทรัพยากร API ของคุณสำหรับการสื่อสารระหว่างเครื่องกับเครื่อง

Gao
Gao
Founder

เมื่อสร้างโปรเจคที่เกี่ยวข้องกับบริการหลายอย่าง ความปลอดภัยของทรัพยากร API จะเป็นความกังวลสำคัญ ในบทความนี้ ฉันจะแสดงวิธีใช้ประโยชน์จาก OAuth 2.0 และ JWT เพื่อรักษาความปลอดภัยการสื่อสารระหว่างบริการ (เครื่องกับเครื่อง) และวิธีใช้การควบคุมการเข้าถึงตามบทบาท (RBAC) ให้เป็นไปตามหลักความสิทธิขั้นต่ำ

เริ่มต้นกันเลย

เพื่อให้ตามทัน ฉันให้คุณมีสิ่งที่จำเป็นต่อไปนี้:

  • บัญชี Logto Cloud หรือ Logto ที่โฮสต์เอง
  • บริการอย่างน้อยสองที่ที่ต้องสื่อสารกัน

เพื่อเป็นการสาธิต ลองสมมติว่าเรามีบริการต่อไปนี้:

  • บริการรถเข็นซื้อของที่มี API เพื่อจัดการรถเข็นซื้อของ
    • จุดปลายทาง: https://cart.example.com/api
  • บริการชำระเงินที่มี API เพื่อประมวลผลการชำระเงิน
    • จุดปลายทาง: https://payment.example.com/api

ขั้นตอนการตรวจสอบสิทธิ์

ตอนนี้ บริการรถเข็นของเราจำเป็นต้องเรียกบริการชำระเงินเพื่อประมวลผลการชำระเงิน ลำดับขั้นตอนการตรวจสอบสิทธิ์มีดังนี้:

แนวคิดสำคัญบางประการในแผนผังข้างต้น:

  • JWT (RFC 7519): JSON Web Token ดู บทความก่อนหน้า สำหรับบทนำเกี่ยวกับ JWT
  • JWK (RFC 7517): JSON Web Key ที่ใช้ยืนยันลายเซ็นของ JWT ชุด JWK คือชุดของ JWK
  • "client_credentials" grant (RFC 6749): ประเภทการอนุญาตใน OAuth 2.0 ใช้ข้อมูลรับรองของไคลเอ็นต์ในการขอรับโทเค็นเข้าถึง เราจะสาธิตรายละเอียดในส่วนต่อไป

ผู้เข้าร่วมแต่ละคนในแผนผังข้างต้นมีบทบาทในลำดับขั้นตอนการตรวจสอบสิทธิ์:

  • Cart service: ไคลเอ็นต์ที่ต้องเรียกบริการชำระเงิน แม้ว่ามันจะเป็นบริการ แต่ในบริบทของ OAuth 2.0 มันยังคงเป็นไคลเอ็นต์ และเราเรียกไคลเอ็นต์เช่นนี้ว่า "应用程序之间的机器-to-machine" ใน Logto
  • Logto: เซิร์ฟเวอร์อนุญาต OAuth 2.0 ที่ออกโทเคนการเข้าถึง
  • Payment service: ทรัพยากร API ที่ให้ API เพื่อประมวลผลการชำระเงิน

มาทำตามลำดับขั้นตอนการตรวจสอบสิทธิ์ทีละขั้นตอนกันเถอะ

การตั้งค่าเริ่มต้น

เพื่อดำเนินลำดับขั้นตอนการตรวจสอบสิทธิ์ เราจำเป็นต้องสร้างแอปพลิเคชันระหว่างเครื่องกับเครื่อง (บริการรถเข็น) และทรัพยากร API (บริการชำระเงิน) ใน Logto

สร้างทรัพยากร API

ตั้งแต่บริการรถเข็นของเราจำเป็นต้องทราบ API ของบริการชำระเงินเมื่อดำเนินการตรวจสอบสิทธิ์ เราจำเป็นต้องสร้างทรัพยากร API ก่อน ไปที่ Logto Console คลิก API resources ในแถบด้านซ้าย แล้วคลิก Create API resource ในกล่องโต้ตอบที่เปิด เรามีบางบทช่วยสอนเพื่อช่วยคุณเริ่มต้น คุณยังสามารถคลิก Continue without tutorial เพื่อข้ามไป

ใส่ชื่อ API และตัวระบุ เช่น Payment service และ https://payment.example.com/api แล้วคลิก Create API resource

หลังจากสร้างทรัพยากร API แล้ว คุณจะถูกเปลี่ยนเส้นทางไปยังหน้ารายละเอียด เราสามารถปล่อยไว้อย่างนั้นสำหรับตอนนี้

สร้างแอปพลิเคชันระหว่างเครื่องกับเครื่อง

คลิก Applications ในแถบด้านซ้าย แล้วคลิก Create application ในกล่องโต้ตอบที่เปิด ค้นหาการ์ด Machine-to-machine แล้วคลิก Start building

ใส่ชื่อแอปพลิเคชัน เช่น Cart service แล้วคลิก Create application จะมีคำแนะนำแบบโต้ตอบเพื่อช่วยคุณตั้งค่าแอปพลิเคชัน คุณสามารถทำตามคำแนะนำเพื่อเข้าใจการใช้งานพื้นฐาน หรือคลิก Finish and done เพื่อข้ามไป

ขอรับโทเค็นการเข้าถึง

เนื่องจากแอปพลิเคชันระหว่างเครื่องกับเครื่องถือว่าปลอดภัย (เช่น ถูกนำไปใช้งานในเครือข่ายส่วนตัว) เราสามารถใช้ OAuth 2.0 "client_credentials" grant เพื่อขอโทเค็นการเข้าถึง มันใช้ basic authentication เพื่อยืนยันตัวตนของไคลเอ็นต์:

  • URL การร้องขอคือจุดสิ้นสุดโทเค็นของ Logto instance ของคุณ คุณสามารถค้นหาและคัดลอกมันได้ในแท็บ Advanced settings ของหน้ารายละเอียดแอปพลิเคชันระหว่างเครื่องกับเครื่อง
  • วิธีการร้องขอคือ POST
  • ส่วนหัว Content-Type ของคำขอคือ application/x-www-form-urlencoded
  • สำหรับส่วนหัว Authorization ค่าเป็น Basic <base64(app_id:app_secret)>, ซึ่ง app_id และ app_secret เป็นรหัสแอปและความลับแอปของแอปพลิเคชันระหว่างเครื่องกับเครื่องตามลำดับ คุณสามารถค้นหามันได้ในหน้ารายละเอียดแอปพลิเคชัน
  • เนื้อหาร้องขอจำเป็นต้องระบุประเภทการอนุญาตและตัวระบุ API ตัวอย่างเช่น grant_type=client_credentials&resource=https://payment.example.com/api
    • grant_type=client_credentials: ค่าเฉพาะสำหรับ "client_credentials" grant
    • resource=https://payment.example.com/api: ตัวระบุ API ของทรัพยากร API ที่ไคลเอ็น ต้องการเข้าสอด
    • หากแอปพลิเคชันจำเป็นต้องได้รับอนุญาตด้วยขอบเขต (สิทธิ์) คุณสามารถระบุขอบเขตในเนื้อหาร้องขอได้ด้วย เช่น `scope=read:payment write:payment เราจะครอบคลุมขอบเขตในภายหลัง.

นี่คือตัวอย่างของคำขอโดยใช้ curl:

เนื้อหาตอบกลับที่สำเร็จจะเป็นอย่างนี้:

ส่งคำขอพร้อมส่วนหัวการตรวจสอบสิทธิ์

ตอนนี้เรามีโทเค็นการเข้าถึงและเราสามารถแนบมันไปในส่วนหัว Authorization ของคำขอไปยังทรัพยากร API ได้ ตัวอย่าง หากเราต้องการเรียก API POST /payments ของบริการชำระเงิน เราสามารถส่งคำขอดังนี้:

ยืนยัน JWT

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

ไลบรารีเหล่านี้มักจะเรียกว่า "jose" (JavaScript Object Signing and Encryption) หรือ "jsonwebtoken" ตัวอย่าง ใน Node.js เราสามารถใช้ jose เพื่อยืนยัน JWT:

ถ้าการตรวจสอบสำเร็จ ตัวแปร payload จะเป็นพย์โหลด JWT ที่ถอดรหัสแล้ว มิฉะนั้นจะมีการโยนข้อผิดพลาด

ใช้การควบคุมการเข้าถึงตามบทบาท

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

ลองสมมติว่าเราต้องการอนุญาตให้บริการรถเข็นสร้างการชำระเงินได้ แต่ไม่ให้มีการอ่านการชำระเงิน

กำหนดสิทธิ์

ใน Logto, "scopes" และ "permissions" นั้นสามารถแทนที่กันได้ ไปที่หน้ารายละเอียดของทรัพยากร API ของบริการชำระเงิน และไปที่แท็บ Permissions ซึ่งควรจะว่างเปล่าตอนนี้ คลิก Create permission, ใส่ read:payment เป็นชื่อสิทธิ์ และใส่ Read payments เป็นคำอธิบายสิทธิ์ จากนั้นคลิก Create permission

ทำซ้ำขั้นตอนข้างต้นเพื่อสร้างสิทธิ์อื่นชื่อ write:payment และคำอธิบาย Create payments

สร้างบทบาทระหว่างเครื่องกับเครื่อง

บทบาทคือกลุ่มของสิทธิ์ ใน Logto, แอพระหว่างเครื่องกับเครื่องสามารถถูกกำหนดบทบาทเพื่อให้สิทธิ์ได้ คลิก "Roles" ในแถบด้านซ้าย แล้วคลิก Create role

  1. ใส่ checkout เป็นชื่อบทบาท และใส่ Checkout service เป็นคำอธิบายบทบาท
  2. คลิก Show more options เลือก "Machine-to-machine app role" เป็นประเภทบทบาท
  3. ในส่วน "Assigned permissions", คลิกไอคอนลูกศรทางซ้ายของชื่อทรัพยากร API (Payment service) และเลือกสิทธิ์ write:payment
    Create role
  4. คลิก Create role
  5. เนื่องจากเรามีแอพระหว่างเครื่องกับเครื่องอยู่แล้ว (Cart service), เราสามารถกำหนดบทบาทให้มันได้ในขั้นตอนถัดไป ทำเครื่องหมายที่ช่องกาเครื่องหมายทางซ้ายของชื่อแอพ (Cart service) และคลิก Assign applications
Assign role to application

ขอรับโทเค็นการเข้าถึงพร้อมขอบเขต

นอกจากพารามิเตอร์เนื้อหาของคำขอที่เรากล่าวถึงใน ขอรับโทเค็นการเข้าถึง, เรายังสามารถระบุขอบเขตในเนื้อหาร้องขอได้ด้วย ตัวอย่างเช่น ถ้าต้องการขอสิทธิ์ write:payment, เราสามารถส่งคำขอที่ดังนี้:

เพื่อขอรับขอบเขตหลายขอบเขต, คุณสามารถแยกมันด้วยช่องว่าง ตัวอย่างเช่น scope=write:payment read:payment

ยืนยันขอบเขต

หากการกระทำจำเป็นต้องมีสิทธิ์ write:payment ในบริการชำระเงิน, เราสามารถยืนยันขอบเขตโดยการยืนยันว่า scope claim ของพย์โหลด JWT:

สรุป

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

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