原文英文版本刊於:5 Common TOTP Mistakes Developers Make (and How to Fix them) - Authgear Blog
你是否常遇到「TOTP 驗證碼無效」的狀況?其實許多開發者在實作 TOTP 時,都會踩到一些常見的狀況或問題:時間不同步、Base32 編碼錯誤、RFC 6238 參數不一致…… 以下整理了五大常見問題,說明發生原因,以及快速修正的方法。
TOTP(時間型一次性密碼)看似簡單,六位數字、每 30 秒更新一次,但細節若處理不好,使用者很快就會卡在登入畫面。
如果你經常看到「Invalid TOTP code」這類錯誤訊息,十之八九就是以下幾個原因造成的。 文末也提供一份快速檢查清單,並附上 Authgear TOTP Authenticator 工具,方便你立即測試設定是否正確(支援 SHA-1/256/512、6–8 位數,以及 30 秒週期)。
問題一:時間不同步(Server 與驗證器時鐘不一致)
症狀
- 驗證碼偶爾失效;使用者回報「有時候可以用、有時候不行」
- 在本機端測試正常,但部署到 CI / Container 後就出錯
原因
TOTP 依賴「時間」計算。只要伺服器與使用者裝置的時間差超過 30–60 秒,驗證碼就會失效。
解決方式
- 與 NTP(網路時間協定)同步時鐘
- 驗證時允許一個小容差(例如 ±1 step),避免因輕微時差導致拒絕使用者
- Log 記錄伺服器時間與驗證碼,方便找出系統間誤差
問題二:密鑰格式錯誤(Base32、Hex、大小寫、補字元)
原因
大部分 TOTP 密鑰是 Base32 編碼,但常見錯誤包括:誤以為是 HEX / ASCII、處理過程中刪掉字元或空白、大小寫處理不正確。
解決方式
- 確認金鑰儲存與傳輸時使用 Base32 編碼
- 從
otpauth://
URI 中解析secret=
參數,確保為 Base32 格式
問題三:RFC 6238 參數不一致(位數、週期、演算法)
原因
TOTP 可配置的參數包括位數、週期、演算法。如果伺服器設定為 8 位數,但使用者端預期 6 位數;或伺服器採用 SHA-256,而 App 使用 SHA-1,就會導致驗證失敗。
解決方式
- 採用常見預設值:6 位數、30 秒週期、SHA-1
- 若需自訂,請確認雙方一致,並參考 RFC 6238 規範
問題四:配置資料錯誤(otpauth URI / QR Code)
原因
otpauth://totp/...
URI 內含 label、issuer、secret、algorithm、digits、period 等參數。若拼字錯誤或遺漏,驗證器就會讀取到錯誤設定。
解決方式
- 驗證並核對配置資料的 URI
- 使用常見驗證器 App(如 Google Authenticator、Authy)交叉測試
問題五:驗證邏輯過於簡化(未處理時差、重複驗證、防暴力破解)
原因
部分實作僅做最基本的比對,忽略了使用者時差、驗證碼重複提交,或缺乏速率限制,容易造成安全風險。
解決方式
- 驗證時允許 ±1 step 容差
- 防止同一驗證碼被重複使用
- 加上速率限制與異常偵測,避免暴力攻擊
快速檢查清單:遇到「TOTP 驗證碼無效」先檢查這些
- ✅ Server 與 NTP 同步
- ✅ 金鑰是否為 Base32 格式
- ✅ 參數是否符合 RFC 6238(位數、週期、演算法一致)
- ✅ 是否與 otpauth URI 中的設定相符
- ✅ 是否已啟用時間容差(verification window)與速率限制
需要快速找出問題嗎?
在正式上線前,先用 Authgear TOTP Authenticator 測試你的金鑰與參數,確認驗證碼正確。