PKCE (Proof Key for Code Exchange)

全名:Proof Key for Code Exchange by OAuth Public Clients
用途:OAuth 2.1 的安全加強機制,防止「授權碼(Authorization Code)」在交換過程中被攔截竊取。


動機:Authorization Code 被攔截的風險

在常見的 Authorization Code Grant 流程中,
Client 需要用 Authorization Code 向 OAuth Provider 換取 Access Token

存在安全風險:

如果 Authorization Code 被惡意第三方攔截,他們可能搶先一步用這個 code 換取 Access Token。

Authorization Code Grant.png

⇒ 這種攻擊稱為 Authorization Code Interception Attack(授權碼攔截攻擊)


授權碼(Authorization Code)是什麼?

假設:

  1. 使用者想讓某個 App Client 存取 Google Drive
  2. Google(OAuth Provider)在使用者同意後,給該 App 一張暫時的票(Authorization Code
  3. App 再透過這張票去換正式的 Access Token(真的能操作資料)

問題:
若駭客攔截這張授權碼,就能偽裝成合法 App → 搶先兌換 Token。


Authorization Code vs API Key

項目 Authorization Code API Key
性質 一次性授權「票據」 固定「通行密鑰
發放對象 經使用者授權的「client」 由開發者生成給某程式
有效時間 很短(數十秒~數分鐘) 通常永久有效或人工撤銷
能直接呼叫 API? ❌ 不行,要換成 Access Token ✅ 可以直接呼叫 API
風險 若被攔截可被搶先換 Token(可用 PKCE 防) 若被洩漏,任何人都能長期使用
用途範例 OAuth 流程(登入 Google / 取得 Token) 後端 API 驗證(開發者 Key、Server 間通訊)

傳統防禦方式:Client Secret(但不適用 Public Client)

OAuth 傳統作法是讓 App 帶上 client_secret(像密碼):

POST /token
Authorization: Basic base64(client_id:client_secret)
code=xxxx

但問題是——Public Client 根本放不住 Secret!

類型 範例 能否安全儲存 Secret?
Confidential Client Server App(後端 API、Web Server) ✅ 可以安全放 secret
Public Client 行動 App、桌面 App、瀏覽器插件、ChatGPT 插件 ❌ 無法保密,容易被反編譯

Public Client 的程式碼跑在使用者裝置上,任何人都能看到設定。


PKCE:沒有 Secret,也能安全

PKCE 用「一次性驗證碼」保護授權碼流程:

  1. App 啟動時生成一個隨機字串 → code_verifier
  2. 對它做 SHA256 → 變成 code_challenge
    傳給 OAuth Provider(如 Google)
  3. Provider 回傳授權碼(Authorization Code)
  4. App 拿授權碼去換 Token 時,再附上原始的 code_verifier
  5. Provider 驗證:「SHA256(code_verifier) 是否等於當初的 code_challenge?」
  6. 若相符 → 確認是同一個 Client → 發 Token

✅ 即使駭客攔截授權碼,也沒有 code_verifier,換不到 Token。


總結

PKCE 是專為「Public Client」設計的防護機制。
它讓沒有 client_secret 的應用,也能透過「一次性挑戰碼」安全地完成 OAuth 授權流程。


OAuth 2.0 學習筆記:理解 PKCE | Danny’s Blog


Powered by Forestry.md