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 Interception Attack(授權碼攔截攻擊)。
授權碼(Authorization Code)是什麼?
假設:
- 使用者想讓某個 App Client 存取 Google Drive
- Google(OAuth Provider)在使用者同意後,給該 App 一張暫時的票(Authorization Code)
- App 再透過這張票去換正式的 Access Token(真的能操作資料)
問題:
若駭客攔截這張授權碼,就能偽裝成合法 App → 搶先兌換 Token。
Authorization Code vs API Key
- OAuth 流程:
User → Auth Server → 發 Authorization Code → Client
→ 換 Access Token → 呼叫 API - API Key:Client 直接攜帶固定 Key 呼叫 API
| 項目 | 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 用「一次性驗證碼」保護授權碼流程:
- App 啟動時生成一個隨機字串 → code_verifier
- 對它做 SHA256 → 變成 code_challenge
傳給 OAuth Provider(如 Google) - Provider 回傳授權碼(Authorization Code)
- App 拿授權碼去換 Token 時,再附上原始的 code_verifier
- Provider 驗證:「SHA256(code_verifier) 是否等於當初的 code_challenge?」
- 若相符 → 確認是同一個 Client → 發 Token
✅ 即使駭客攔截授權碼,也沒有 code_verifier,換不到 Token。
總結
PKCE 是專為「Public Client」設計的防護機制。
它讓沒有 client_secret 的應用,也能透過「一次性挑戰碼」安全地完成 OAuth 授權流程。
OAuth 2.0 學習筆記:理解 PKCE | Danny’s Blog