什麼是 PKCE:從基本概念到深入理解
本文解釋了 PKCE(驗證碼交換證明)如何通過防止惡意應用攔截授權碼來保護 OAuth 2.0 授權碼流程,帶你從基本概念到全面理解。
驗證碼交換證明 (PKCE) 是 授權碼流 的一個擴展,最初設計用於在行動應用中保護授權碼流,而現在也建議單頁應用使用。從 OAuth 2.1 開始,PKCE 對所有類型的客戶端,包括 公開客戶端 和 機密(私人)客戶端,都被強制執行。
在本文中,我們將幫助你了解 PKCE 為什麼被創建以及它如何保護你的應用程序,並讓你深入理解 PKCE。
為什麼需要 PKCE?
在 OAuth 2.0 授權碼流中,用戶通過應用程序請求登入。認證伺服器將用戶導向一個認證頁面。在用戶認證後,伺服器將授權碼返回給應用程序,然後它使用此代碼從認證伺服器請求一個訪問權杖。
此流程有一個顯著的安全風險:授權碼可能被惡意程式攔截。這在行動設備上尤其令人擔憂,因為其他應用程序可能註冊相同的重定向 URI 並攔截授權碼。
下圖顯示了攔截過程:
步驟 (1):應用程序通過無法攔截的安全 API 發起授權請求。這一步,請求者還需提供重定向 URI。
步驟 (2):請求隨後被轉接至 OAuth 2.0 授權伺服器。由於 OAuth 要求使用 TLS,此通訊受到 TLS 保護,無法被攔截。
步驟 (3):授權伺服器返回授權碼。
步驟 (4.a):授權碼透過在步驟 (1) 中提供的重定向 URI 返回給請求者。如果惡意應用註冊為重定向 URI 的處理程序,則它可以攔截授權碼。擁有授權碼,攻擊者可以在步驟 (5.a) 和 (6.a) 中請求並獲得訪問權杖。
如上所示,在 OAuth 2.0 授權碼流中,如果授權碼被攔截,攻擊者可以用其獲取訪問權杖。因此,我們需要一個機制來防止授權碼遭到攔截,這導致了 PKCE 的創建。
PKCE 如何運作?
如上所述,如果我們想要防止被攻擊,就必須確保只有發起請求的應用程序可以請求並獲得訪問權杖。這就是 PKCE 的作用所在。
PKCE 通過引入 "驗證碼" 概念解決此問題。
在請求授權碼時,應用程序首先生成一個隨機驗證碼並將其存儲在本地。然後,它使用特定的算法將此驗證碼轉換成一個驗證挑戰。應用程序在授權碼請求期間將驗證挑戰和驗證挑戰方法一起發送給認證伺服器。
驗證碼是一個隨機生成的字符串,而驗證挑戰是通過轉換生成的。支持兩種轉換方法:
plain
:直接將驗證碼作為驗證挑戰。
S256
:對驗證碼應用 SHA-256 散列,然後進行 Base64URL 編碼。由於散 列輸出無法逆向獲得驗證碼,而且因為plain
方法可能在傳輸期間易於遭中間人攻擊,因此強烈建議為了安全起見使用S256
。
用戶認證後,認證伺服器將授權碼返回給應用程序。在請求訪問權杖時,應用程序會將授權碼和驗證碼一起發送給認證伺服器。伺服器使用先前接收到的 "驗證挑戰方法" 轉換 "驗證碼",並將結果與先前接收到的 "驗證挑戰" 進行比較,以驗證客戶端擁有 "驗證碼"。
步驟 (1-3):應用程式創建並記錄一個名為 "驗證碼" 的秘密,並衍生一個已轉化的版本 "驗證挑戰",這會在 OAuth 2.0 授權請求中與轉化方法 "驗證挑戰方法" 一起發送。
步驟 (3-6):認證伺服器按常規回應,但會記錄 "驗證挑戰" 和 "驗證挑戰方法"。
步驟 (7.a):應用程式然後將授權碼如常發送至權杖端點,但會包含在步驟 (1) 中生成的 "驗證碼" 秘密。
步驟 (8.a-9.a):授權伺服器將 "驗證碼" 轉化為 "驗證挑戰" 並與步驟 (1-3) 的 "驗證挑戰" 進行比較。如果不相等則拒絕授權。
在此情況下,即便惡意應用在步驟 (6.b) 攔截了授權碼,它也無法兌換成訪問權杖,因為它無法持有 "驗證碼" 秘密;而且由於 "驗證碼" 是通過 TLS 傳輸,無法被攔截。
總結
本文解釋了 PKCE 的運作方式及其為什麼對於保護授權碼流是必要的。通過添加驗證碼機制,PKCE 防止惡意應用攔截和濫用授權碼。希望此解釋能幫助你深入理解 PKCE。