Skip to content
All writing Part 06 of 07 · 一次 JWT 稽核背後的七個盲點
Engineering · 3 min read

存取與刷新令牌輪替

一個 token 逼你在安全和體驗之間二選一。兩個 token 搭配輪替和 reuse detection,攻擊窗口縮到 15 分鐘。

一個 token 逼你做取捨:短 TTL(安全,但體驗差)或長 TTL(體驗好,但攻擊窗口大)。兩個 token 解決這個問題。

登入 Access (15 min) Refresh R1 (7d) API 呼叫 過期 /refresh R1 有效? 發行 R2 R1 → "已用" R1 已用過? 重複使用 → 撤銷整個家族 過期 → /refresh 透過 reuse detection 抓到竊取
AccessRefresh
TTL5-15 分鐘1-7 天
送往每個 API endpoint只有 /refresh
儲存位置記憶體(JS 變數)httpOnly cookie
JS 能讀?是(Authorization header)否(擋住 XSS)
audmy-appmy-refresh

每個 refresh token 帶一個唯一的 jti。Server 追蹤它的狀態:activeused/refresh 發行新的一對後,舊 token 變成 used。再次使用 used 的 token 會觸發 reuse detection,server 撤銷整個 token 家族。15 分鐘的 access TTL 限制了攻擊窗口。真正用戶的 token 過期後,/refresh 呼叫就會抓到竊取。

Cookie 旗標httpOnly 是 cookie 旗標,不是協定):

  • HttpOnly:對 JavaScript 隱藏 cookie。
  • Secure:只透過 HTTPS 送出 cookie。
  • SameSite=Strict:阻擋跨站請求攜帶 cookie。

稽核中的發現: auth-service 簽 access token 用 aud: 'my-app',refresh token 用 aud: 'my-refresh'。輪替時從 DB 重新取最新的 email 和 displayName。

「一個 token 是取捨。兩個 token 是解法。」

參考來源

回到總覽:一次 JWT 稽核背後的七個盲點 · 六個標準宣告 · iss 宣告 · 演算法混淆與 none 攻擊

Tags #jwt #security #authentication
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Youtube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration