Vibe Coder
API Key、OAuth、JWT,身份與授權怎麼選
API Key、OAuth 2.0、JWT 分別回答不同的問題:這是哪個應用程式、使用者是否同意授權、Token 裡帶了什麼身份聲明。後端呼叫外部 API 用 API Key,第三方登入用 OAuth,前後端傳遞登入狀態用 JWT。
API Key、OAuth、JWT,身份與授權怎麼選
API Key 放錯位置、OAuth Token 沒有 refresh、JWT 沒有驗簽,這些錯誤都會讓 API 直接拒絕你。搞混三種機制的下場,永遠是一個又一個的 401。這一課把認證和授權兩件事分清楚,也把三種機制的使用場景整理成一張決策樹。
這一節也是後面 OAuth 實作與 Webhook 驗證的基礎,先把觀念打穩,後面的實作課才不會一頭霧水。
你將學到什麼
三種機制總覽
API Key、OAuth 2.0、JWT 各自回答什麼問題,風險在哪裡。
API Key 的三個鐵則
最簡單也最危險的機制,怎麼存、怎麼撤銷、絕不能出現在程式碼裡。
OAuth 2.0 的核心概念
讓使用者授權,不用把密碼交給你的 App。
什麼場景用什麼
一張決策樹,對照你的需求直接選對機制。
認證與授權:兩件不同的事
認證(Authentication):確認你是誰,例如這個 API Key 是屬於哪個帳號。授權(Authorization):確認你能做什麼,例如這個帳號有讀取的權限,但沒有刪除的權限。英文常縮寫成 AuthN 和 AuthZ。
三種機制總覽
| 機制 | 回答什麼問題 | 使用場景 | 風險 |
|---|---|---|---|
| API Key | 這是哪個應用程式 | 機器對機器,後端呼叫外部 API | 洩漏即全開,需要輪換 |
| OAuth 2.0 | 使用者同意讓這個應用存取它的資料嗎 | 第三方登入、代表使用者操作 | Token 過期要 refresh |
| JWT | 這個 Token 裡帶了什麼聲明 | 前後端傳遞身份、微服務間驗證 | 過期前無法撤銷 |
API Key:最簡單也最危險
API Key 是一個長字串,代表你的身份,就像密碼,但通常只給程式用,不給人輸入。
# .env 檔案,不能 commit 到 Git
OPENAI_API_KEY=sk-proj-abc123...
# Python 程式裡,從環境變數讀取
import os
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
# 放在 Header 裡傳給 API
headers = {"Authorization": f"Bearer {api_key}"}
# 或某些 API 用自訂 Header
headers = {"X-API-Key": api_key}
API Key 的三個鐵則永遠放在環境變數,不管任何理由都不能出現在程式碼裡;確認忽略清單裡有這個環境變數檔案,不會被 commit 進 Git;洩漏就立刻撤銷,不管是不小心 commit 了還是截圖截到,立刻到提供商網站撤銷這個 Key 並重新申請。GitHub 有自動掃描機器人,Key 一 commit 上去,幾分鐘內就可能被偵測到並被有心人使用。
OAuth 2.0:讓使用者授權,不交出密碼
OAuth 解決的問題是:讓使用者授權你的 App 存取他在其他平台的資料,但不需要把密碼交給你的 App。Google 登入、GitHub 登入背後都是 OAuth 2.0。
- 使用者點用 Google 登入,你的 App 把使用者導到 Google 的授權頁面。
- 使用者在 Google 的頁面上同意授權,Google 把一個 Authorization Code 傳回你的 App。
- 你的 App 用這個 Code 向 Google 換取 Access Token,也就是代表使用者的通行證。
- 用 Access Token 呼叫 Google API,取得使用者資料,例如名稱與 Email。
- Access Token 過期後,用 Refresh Token 換新的,不需要使用者重新登入。
為什麼要多一步,先換 Code 再換 TokenAuthorization Code 只能用一次,即使被截取也沒用。換成 Access Token 的步驟在伺服器對伺服器之間完成,不經過使用者的瀏覽器,更安全。
JWT:帶著走的身份證
JWT(JSON Web Token)是一個可以驗證真偽的 Token,裡面帶著身份和權限資訊,不需要查資料庫就能驗證,速度快。
# Header,演算法說明
{"alg": "HS256", "typ": "JWT"}
# Payload,帶著的資訊
{"sub": "user_123", "name": "Joan",
"role": "admin", "exp": 1756339200}
# Signature,防偽簽名,用 secret 算出來的
HMACSHA256(base64(header) + "." + base64(payload), secret)
| 欄位 | 說明 |
|---|---|
| sub | Subject,通常是使用者 ID |
| exp | Expiration,過期時間,Unix timestamp 格式 |
| role | 使用者角色,自訂欄位,不是標準 |
什麼場景用什麼:決策樹
| 場景 | 用什麼 | 理由 |
|---|---|---|
| 後端呼叫外部 API,例如 OpenAI | API Key | 最簡單,機器對機器 |
| 讓使用者用 Google 或 GitHub 登入 | OAuth 2.0 | 使用者授權,不需要密碼 |
| 前後端之間傳遞登入狀態 | JWT | 帶著身份資訊,不用查資料庫 |
| 微服務之間互相呼叫 | JWT 或 API Key | 依安全需求選擇 |
| Webhook 驗證來源 | HMAC Signature | 下一課會詳細說明 |
延伸學習
常見問答
認證和授權有什麼不同?
認證是確認你是誰,例如確認這個 API Key 屬於哪個帳號;授權是確認你能做什麼,例如這個帳號有沒有刪除資料的權限。兩件事常常被混為一談,但機制設計上是分開的兩步。
API Key 洩漏了怎麼辦?
不管是不小心 commit 上 Git 還是截圖截到,都要立刻到 API 提供商的後台撤銷這個 Key,並重新申請一個新的,不要猶豫或先確認再處理。
為什麼 Google 登入不直接把密碼給我的 App?
這正是 OAuth 2.0 要解決的問題,讓使用者授權你的 App 存取他在 Google 的資料,但完全不需要把 Google 密碼交給你的 App,安全性高很多。
JWT 裡面可以放密碼之類的敏感資訊嗎?
不行。JWT 的 Payload 只是用 base64 編碼,不是加密,任何人都能解碼看到內容,只有簽名部分能防止竄改,敏感資訊絕對不能放進去。

