1. 題目與使用場景
公司有多個 API 資源伺服器,存取令牌由授權伺服器簽發。資源伺服器需要知道令牌是否 active、屬於哪個客戶端、擁有哪些 scope 以及何時過期;安全團隊還要求能快速撤銷被盜令牌。設計要平衡即時撤銷、低延遲和授權服務可用性。
2. 面試官考察點
- 是否理解 RFC 7662 introspection 回應與 RFC 7009 撤銷語義。
- 是否能設計快取、撤銷事件和版本,使「已撤銷」不會長期被舊快取掩蓋。
- 是否區分不透明令牌、JWT 本地校驗和 DPoP 等持有證明。
- 是否為授權服務不可用、網路重試、租戶隔離和稽核提供明確策略。
3. 回答前需要釐清的問題
- 令牌是短效 access token、refresh token,還是兩者都要 introspect?
- 撤銷目標是單個令牌、授權授予、使用者工作階段還是整個客戶端?
- 資源伺服器能接受多長的撤銷傳播延遲?
- 是否需要綁定客戶端金鑰或 DPoP 公鑰,防止 bearer token 被複製後重放?
4. 30 秒回答框架
用「端點—狀態源—快取—撤銷傳播—故障策略」回答:
授權伺服器提供受保護的 introspection 和 revocation 端點,狀態庫保存令牌雜湊、客戶端、scope、過期和撤銷版本。資源伺服器按短 TTL 快取 active 結果,同時訂閱撤銷事件立即刪除相關快取;高風險 scope 在授權服務不可用時拒絕,低風險請求只在未過期的正快取內短暫放行。所有查詢、撤銷和失敗都寫入稽核。
5. 分步驟深入解答
第一步:定義令牌狀態與端點權限
Introspection 請求只允許受信任的資源伺服器呼叫,回傳 active、client_id、username、scope、exp、iat、sub 等必要欄位,避免洩露多餘身分資訊。撤銷端點應驗證呼叫方和令牌類型,按 RFC 7009 處理重複撤銷,不能因令牌已失效就洩露其存在性。
第二步:設計狀態儲存與索引
以令牌指紋或雜湊作為主鍵,保存簽發時間、過期時間、授權授予 ID、客戶端、scope、狀態版本和撤銷原因。按授權授予 ID 建立批量撤銷索引;敏感原文不進入日誌。資料分片按租戶或雜湊分布,避免單個客戶端成為熱點。
第三步:處理快取與撤銷傳播
正結果可以短 TTL 快取,負結果通常不應長時間快取。撤銷後發布帶令牌指紋和狀態版本的事件,資源伺服器刪除本地條目;事件遺失時由版本檢查或定期拉取修復。對高風險操作可強制線上 introspect,犧牲延遲換取即時性。
第四步:故障、重試與持有證明
對 introspection 逾時使用指數退避和熔斷,避免資源伺服器把授權服務壓垮。授權服務不可用時按 scope 風險選擇 fail-closed 或短暫使用尚未過期的正快取。若採用 DPoP,資源伺服器還要驗證請求證明與令牌綁定的公鑰,降低純 bearer token 被複製後的重放風險。
6. 高品質示範回答
我會把系統拆成授權端點、introspection 服務、撤銷服務、狀態儲存、撤銷事件總線和資源伺服器 SDK。狀態庫以令牌雜湊為鍵,保存 client、scope、iat、exp、授權授予 ID、撤銷狀態和版本。introspection 只回傳資源伺服器需要的欄位,並要求呼叫方認證。
>
SDK 對普通 scope 快取 active 結果三十秒,對高風險 scope 每次線上查詢。撤銷介面支援單令牌和按授權授予批量撤銷,成功後發送帶版本的事件;SDK 收到事件立即刪除快取,定時任務補償遺失事件。正結果快取到期前如果版本不匹配,也必須重新查詢。
>
授權服務逾時時,低風險請求可以使用尚未過期的正快取,高風險請求直接拒絕;熔斷和抖動重試防止級聯故障。若使用 DPoP,SDK 額外驗證請求證明和綁定公鑰。查詢、撤銷、快取命中和故障都寫入脫敏稽核,便於追蹤被盜令牌的傳播範圍。
7. 常見錯誤
- 把 JWT 本地簽章驗證當成即時撤銷方案。
- 長時間快取 active 結果,卻沒有撤銷事件或版本校驗。
- introspection 端點對公網開放,或回傳不必要的使用者欄位。
- 授權服務故障時所有請求都 fail-open,放大被盜令牌風險。
- 重試沒有逾時、熔斷和抖動,導致認證流量雪崩。
8. 追問及應對
追問一:為什麼負快取通常要更短?
令牌可能剛簽發、網路讀到舊副本或撤銷狀態正在傳播。短負快取能減少把暫時性不存在誤判為永久無效的窗口。
追問二:撤銷 refresh token 是否應同時撤銷 access token?
按授權授予和安全策略決定。若 refresh token 被盜,通常應撤銷該授予下的剩餘令牌,並讓資源伺服器透過版本或事件盡快失效快取。
追問三:如何防止撤銷事件重複或亂序?
事件攜帶單調遞增版本或撤銷時間,消費者只接受不舊於本地狀態的版本;重複事件保持冪等,亂序事件不會把已撤銷狀態恢復為 active。