保護 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 資源,然後點擊 創建 API 資源。在開啟的對話框中,我們提供了一些教程幫助你開始使用。你也可以點擊 繼續而不使用教程 以跳過它。
輸入 API 名稱和標識符,例如 Payment service 和 https://payment.example.com/api,然後點擊 創建 API 資源。
創建 API 資源後,你會被重定向到詳細信息頁面。現在我們可以暫時不處理它。
點擊左側邊欄中的 應用程序,然後點擊 創建應用程序。在開啟的對話框中,找到 機器對機器 卡片,然後點擊 開始構建。
輸入應用程序名稱,例如 Cart service,然後點擊 創建應用程序。將顯示一個互動指南來幫助你設置應用程序。你可以按照指南瞭解基本用法,或者點擊 完成並完成 以跳過它。
由於假設機器對機器應用程序是安全的(例如,它們部署在私有網絡中),因此我們可以使用 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" 或 "jsonwebtoken"。例如,在 Node.js 中,我們可以使用 jose 驗證 JWT:
如果驗證成功,payload 變量將是已解碼的 JWT 主體。否則,將拋出錯誤。
現在,我們已經成功保護了購物車服務和支付服務之間的通信。然而,驗證流程僅能確保客戶端是真正的購物車服務,並不能確保購物車服務有任何權限在支付服務上執行動作。
比如說,我們想允許購物車服務創建支付,但不允許它讀取支付記錄。
在 Logto 中,"範圍" 和 "權限" 是可以互換的。在支付服務的 API 資源詳細信息頁面上,導航到 權限 標籤頁。現在應該是空的。點擊 創建權限,輸入 read:payment 作為權限名稱,並輸入 讀取支付記錄 作為權限描述。然後點擊 創建權限。
重複上述步驟以創建另一個名為 write:payment 並描述為 創建支付記錄 的權限。
角色是一組權限組合。在 Logto 中,機器對機器應用程序可以被指派角色以授予權限。在左側邊欄中點擊 "角色",然後點擊 創建角色。
checkout 作為角色名稱,並輸入 結算服務 作為角色描述。write:payment 權限。


除了我們在請求訪問令牌中提到的請求主體參數外,我們還可以在請求主體中指定範圍。例如,如果我們想請求 write:payment 權限,我們可以發送以下請求:
要請求多個範圍,你可以用空格分隔它們。例如,scope=write:payment read:payment。
如果需要支付服務中的某個動作需要 write:payment 權限,我們可以通過斷言 JWT 主體的 scope 聲明來驗證範圍:
如果你想保護對購物車服務的訪問,你也可以應用相同的驗證流程。這一次,購物車服務是 API 資源,而客戶端是需要訪問的另一個服務。
使用 Logto,你的 API 資源通過 OAuth 2.0 和 JWT 得到保護,並且你可以通過應用基於角色的訪問控制來遵循最低權限原則。此外,你也可以使用 Logto 管理你的用戶及其權限,甚至與第三方身份提供者集成。