為機器間通訊保護你的 API 資源
學習如何利用 OAuth 2.0 和 JWT 來保障你的 API 資源,用於機器間通訊。
學習如何利用 OAuth 2.0 和 JWT 來保障你的 API 資源,用於機器間通訊。
當建立一個涉及多個服務的項目時,API 資源的安全性是一個關鍵問題。在這篇文章中,我將向你展示如何利用 OAuth 2.0 和 JWT 來保障服務之間的通訊(機器對機器),以及如何應用基於角色的存取控制(RBAC)來遵循最低權限原則。
為了跟隨本文,我假設你已具備以下先決條件:
為了演示目的,讓我們假設我們有以下服務:
https://cart.example.com/apihttps://payment.example.com/api現在,我們的購物車服務需要調用支付服務以處理支付。認證流程如下:
以上圖中的一些關鍵概念:
在上述圖中,每個參與者都在認證流程中扮演一個角色:
讓我們一步一步地了解認證流程。
要執行認證流程,我們需要在 Logto 中創建一個機器對機器應用(購物車服務)和一個 API 資源(支付服務)。
由於我們的購物車服務在進行認證時需要了解支付服務的 API,因此我們需要先創建一個 API 資源。 進入 Logto 控制台,在左側邊欄點擊 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" 授權來獲取訪問權杖。它使用 基本認證 來驗證客戶端:
POST。Content-Type 標頭是 application/x-www-form-urlencoded。Authorization 標頭,值是 Basic <base64(app_id:app_secret)>,其中 app_id 和 app_secret 是機器對機器應用的應用 ID 和應用密鑰。你可以在應用詳情頁找到它們。grant_type=client_credentials&resource=https://payment.example.com/api。
grant_type=client_credentials: "client_credentials" 授權的常量值。resource=https://payment.example.com/api: 客戶端希望訪問的 API 資源的 API 標識符。scope=read:payment write:payment。我們稍後會介紹範圍。以下是使用 curl 的請求示例:
成功的響應正文可能如下:
現在我們有了訪问權杖,我們可以將其附加到 API 資源請求的 Authorization 標頭中。例如,如果我們想調用支付服務的 POST /payments API,我們可以發送以下請求:
你可能注意到支付服務需要使用 JWK 集驗證 JWT,並可能有一個本地 JWK 集緩存以避免每次都從 Logto 獲取 JWK 集。幸運的是,由於 JWT 的普及,有許多庫可以幫助你用幾行代碼達成目標。
這些庫通常稱為 "jose"(JavaScript Object Signing and Encryption)或 "jsonwebtoken"。例如,在 Node.js 中我們可以使用 jose 來驗證 JWT:
如果驗證成功,payload 變量將是解碼的 JWT 載荷。否則,將拋出錯誤。
現在我們已經成功的保護了購物車服務和支付服務之間的通訊。然而,認證流程只能確保客戶端是真正的購物車服務,卻不能確保購物車服務有權執行支付服務上的操作。
假設我們想允許購物車服務創建支付,但不允許讀取支付。
在 Logto 中,"範圍" 和 "許可權" 是可以互換的。前往支付服務的 API 資源詳情頁,並導航到 Permissions 標籤。現在應該是空的。點擊 Create permission,輸入 read:payment 為許可權名稱,並輸入 Read payments 作為許可權描述。然後點擊 Create permission。
重複上述步驟以創建另一個名為 write:payment 描述為 Create payments 的許可權。
角色是一組許可權。在 Logto 中,機器對機器應用可以分配角色以授予許可權。在左側邊欄點擊 "Roles",然後點擊 Create role。
checkout 作為角色名稱,並輸入 Checkout service 為角色描述。write:payment 許可權。


除我們在 請求訪問權杖 中提到的請求正文參數之外,我們也可以在請求正文中指定範圍。例如,如果我們想請求 write:payment 許可權,我們可以發送以下請求:
要請求多個範圍,你可以用空格分隔。例如:scope=write:payment read:payment。
如果在支付服務中一個操作需要 write:payment 許可權,我們可以通過確認 JWT 載荷中的 scope 聲明來驗證範圍:
如果你想保護購物車服務的訪問,你也可以應用相同的認證流程。這次,購物車服務是 API 資源,而客戶端是另一個需要訪問的服務。
通過 Logto,你的 API 資源被 OAuth 2.0 和 JWT 保護,並且你可以通過應用基於角色的存取控制來遵循最低權限原則。此外,你還可以利用 Logto 管理你的用戶及其許可權,甚至可以與第三方身份提供者整合。