每一段都是證據 · 每個結論都要說明依據
能解碼,不代表已通過驗證。
看得見 Header 與 Payload,只代表兩段 Base64URL 可以解析成 JSON。信任還需要固定允許的演算法、匹配的本機金鑰、有效的時間範圍,以及明確設定的 issuer、audience 與應用程式 Claims 政策。
Header
{ "alg": "HS256", "typ": "JWT" }Payload
{ "sub": "123", "aud": "devsexy-api", "exp": 1766073600 }Signature
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c解碼並驗證公開測試權杖
兩個範例使用同一份公開 HS256 測試資料,對照可讀 payload 與指定演算法、金鑰、簽發者、受眾及時間下的驗證。
載入範例會取代權杖及全部選項,包括金鑰。此公開測試資料不提供任何存取權限,金鑰不可用於真實應用程式。
讀取宣告,不信任簽章
解碼 · HS256 · 不提供金鑰。權杖已在 2024 年到期,解碼仍能讀取宣告。
輸入
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkZW1vLXVzZXIiLCJpc3MiOiJodHRwczovL2lzc3Vlci5leGFtcGxlLnRlc3QiLCJhdWQiOiJkZXZzZXh5LWRlbW8iLCJuYmYiOjE3MTAwMDAwMDAsImV4cCI6MTcxMDAwMzYwMH0.gAP2idduo9EHFyecHJohqwzl7F3g8Bvp3xDvVWyCHsI
主體是 demo-user,輸出明確表示未檢查簽章。
"sub": "demo-user" Signature: not checked — decoding never proves authenticity
在有效期間內的固定時間驗證
驗證 · HS256 · 公開測試金鑰 devsexy-public-example-key-do-not-use-in-production · 簽發者 https://issuer.example.test · 受眾 devsexy-demo · 驗證時間 1710001800 秒 · 時鐘容差 0。
輸入
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkZW1vLXVzZXIiLCJpc3MiOiJodHRwczovL2lzc3Vlci5leGFtcGxlLnRlc3QiLCJhdWQiOiJkZXZzZXh5LWRlbW8iLCJuYmYiOjE3MTAwMDAwMDAsImV4cCI6MTcxMDAwMzYwMH0.gAP2idduo9EHFyecHJohqwzl7F3g8Bvp3xDvVWyCHsI
在指定歷史時刻驗證通過。清空驗證時間後使用目前時鐘,此權杖已到期;歷史通過不代表目前有存取權限。
Signature: verified with the selected HS256 key, claim, and clock policy Issuer policy: https://issuer.example.test Audience policy: devsexy-demo
信任階梯
每一階只證明下一件事。
Compact 結構
剛好有三個非空的 Base64URL 段
JSON 可解碼
Header 與 Claims 可讀,但內容仍不可信
簽章已驗證
所選演算法與金鑰證明內容完整性
時間可接受
依驗證時間與 clock skew 檢查 exp / nbf
Issuer/Audience 符合
只有填入預期值時才會成為驗證條件
自訂政策符合
指定路徑的 Claims 通過;授權與撤銷仍在系統端
演算法/金鑰契約
Token 的 alg 是輸入,不是安全政策。
HS256 / 384 / 512UTF-8 shared secret簽署與驗證使用完全相同的文字 secret
支援;空 secret 會拒絕
RS256 / 384 / 512 · PS256 / 384 / 512RSA PEMPKCS#8 私鑰簽署;X.509、SPKI 或 PKCS#8 驗證
支援;key 與 alg 必須匹配
ES256 / 384 / 512EC PEMPKCS#8 私鑰簽署;X.509、SPKI 或 PKCS#8 驗證
支援;曲線必須匹配
JWK / JWKS / none / EdDSA未受理不讀取遠端 key set,也不接受 unsecured JWT
不在目前 allowlist
NumericDate 時鐘
JWT 時間 Claims 使用 Unix epoch 秒數。
現在 · 1,716,073,600
iat1,716,070,000簽發於 60 分鐘前nbf1,716,072,700已可使用 15 分鐘exp1,716,075,400將於 30 分鐘後過期把毫秒誤當成秒,日期會偏到數萬年以後。Clock skew 是驗證器明確設定的有限秒數容差,不是忽略 exp;iat 會顯示,但目前不檢查 token age。
Issuer/Audience 檢查點
簽章正確,仍可能是錯的簽發者或錯的使用對象。
isshttps://id.example.test/與填入的 trusted issuer 精確比對
aud["devsexy-api", "account"]Claim 必須包含填入的單一 audience
tenantproduction-eu可用自訂 assertion 比對的 private Claim
scopetools:read可檢查字面值;實際授權仍由 resource server 決定
Debugger 風險檯
把這裡當成會接觸 Bearer Token 與金鑰的敏感工作區。
Bearer Token 外洩
高風險URL、截圖、log、剪貼簿記錄與 issue 中的 Token 都可能被重放。
弱 HMAC secret
高風險工具不評估 secret 強度;太短或可猜的值可能遭離線暴力嘗試。
演算法混淆
嚴重驗證會固定單一 allowlist 項目,並要求 Header alg 完全相同。
不受信任的 kid / jku / x5u
高風險只顯示 Header;不會把 key hint 轉成檔案讀取或網路請求。
瀏覽器內簽署
需審查Worker 使用貼入的本機金鑰;仍只應放測試金鑰,正式私鑰應留在受控環境。
檢查權杖周邊的證據
不是完整三段 JWT 的編碼文字,可使用 Base64 工具。
核對 UTC 時刻,避免把秒誤當成瀏覽器毫秒。
另外核對查詢跳脫;URL 解析不能驗證權杖身分。
使用離線工具箱反覆檢查,並使用測試憑證。