JWT 產生器
密鑰僅在本頁使用,不會傳送、儲存,也不會加入網址,因此分享連結不會外洩密鑰。但請勿將正式環境的簽章密鑰貼到任何網站,包括本站;測試請使用臨時密鑰。
僅支援 HS256、HS384 與 HS512。RS、ES、PS 簽章需要私密金鑰,本工具刻意不要求提供。
您輸入的內容不會被儲存、記錄或分享。
編輯 JWT 內容、選擇演算法,並以您的密鑰簽章。簽章完全在瀏覽器中完成,密鑰不會離開您的裝置。
使用方式
- 以 JSON 格式編輯內容。
- 可選擇有效期限,系統會自動加入 iat 與 exp。
- 輸入密鑰後,簽署完成的權杖會顯示在下方。
簽章會產生什麼
JWT 是以點號連接的三個 base64url 區段。第一個是標頭,說明使用了哪種演算法;第二個是酬載,存放你的宣告;第三個是簽章,是對前兩個區段以點號連接後的內容計算而得。被簽署的是這些區段的確切位元組,而不是它們解碼後的 JSON,這就是為什麼重新序列化權杖會讓它失效。
使用 HS256 時,簽章是以你的密鑰對簽署內容計算的 HMAC。任何持有相同密鑰的人都能重新計算並確認是否相符,這證明了兩件事:權杖是由知道密鑰的人簽發的,而且之後內容沒有被改動。只要改動酬載中的一個字元,重新計算出的簽章就不再相符。
它做不到的是隱藏任何東西。酬載只是編碼,並未加密,任何持有權杖的人不需要密鑰就能讀到每一項宣告。絕對不要把密碼、卡號,或任何你不願出現在日誌中的資料放進 JWT 酬載。
如何選擇密鑰
RFC 7518 要求 HMAC 金鑰長度至少等於雜湊輸出長度:HS256 為 256 位元,HS384 為 384 位元,HS512 為 512 位元。也就是說至少要 32 個隨機位元組,而不是一句好記的片語。
原因在於 JWT 本身就是離線攻擊的全套材料。它同時包含簽署內容與簽章,所以任何人只要拿到一個權杖,就能以硬體允許的最快速度嘗試候選密鑰,不需要網路往返,也沒有任何速率限制。坊間早有公開工具專門做這件事,字典裡的單字或短字串幾秒內就會被破解。使用弱密鑰的權杖一旦外洩,攻擊者就能自行簽發帶有任意宣告的權杖。
請使用密碼管理器或金鑰產生器產生的隨機值,每個環境使用不同的密鑰,避免測試環境的權杖被拿去對正式環境重放,並像其他憑證一樣定期輪換。
值得設定的宣告
除了應用程式需要的內容之外,RFC 7519 還註冊了一小組標準宣告。iss 表示簽發者,sub 表示主體,aud 表示預期的接收者,jti 則為權杖提供唯一 ID,以便個別撤銷或檢查是否被重放。三個時間宣告,也就是代表到期的 exp、代表最早生效時間的 nbf、代表簽發時間的 iat,都是 NumericDate 值,意即自 Unix 紀元起算的秒數。
是秒,不是毫秒。直接填入 JavaScript 時間戳記,是手寫權杖遭拒最常見的單一原因:十三位數的 exp 會被解析成遙遠未來的日期,有些函式庫會直接拒絕,有些則會把它當成永不過期的權杖接受。
設定 exp 本身並不會讓權杖過期。權杖之所以過期,是因為驗證方檢查了這個宣告;只檢查簽章的驗證方,會欣然接受去年的權杖。由於簽發與驗證的機器時鐘很少完全一致,多數函式庫也允許少量的時鐘誤差,通常是一到兩分鐘。
為什麼只支援 HS 演算法,以及 alg 的陷阱
HS 家族是對稱式的:同一把共用密鑰既用來簽署也用來驗證,所以只用你輸入的內容就能在這裡完成簽署。RS、ES 與 PS 是非對稱式的,需要把私密金鑰貼到網頁上,而這是本工具不願要求你做的事。
標頭中註明演算法的欄位,也正是兩個知名攻擊的所在。第一個是 alg: none,宣告權杖未經簽署;接受它的函式庫,可能被塞進簽章為空的偽造權杖。第二個是演算法替換:拿一個以 RS256 簽署的權杖,把標頭改成 HS256,再用簽發者的公開金鑰當作 HMAC 密鑰重新簽署。從權杖讀取演算法、而非事先決定的驗證方,會順利通過驗證,因為公開金鑰並不是秘密。
兩者的防禦方式相同,而且應該放在驗證方而非簽發方:在驗證呼叫中固定預期的演算法,拒絕任何標頭與之不符的權杖。
設計權杖的生命週期
權杖系統中影響最深遠的一個決定,就是權杖能存活多久,因為 JWT 在過期之前無法收回。短生命週期,也就是存取權杖設為五到十五分鐘,能把權杖外洩後的風險窗口壓到很小,這也是標準做法:再搭配一個生命週期較長、但因為存在伺服器上而可以撤銷的更新權杖。
更新權杖輪替讓這組搭配安全得多:每次更新都會簽發新的更新權杖並讓舊的失效,所以被偷走的權杖只能用一次。如果舊的那一個再次被提出,伺服器就知道有兩方同時持有它,可以把整個家族一起撤銷。
如果真的需要一份長期有效的憑證,例如機器對機器的整合或 CLI 工具,JWT 通常不是合適的形式。改用對照資料庫檢查的 API key,可以立即撤銷、精確地限定權限範圍,並顯示在介面上讓擁有者看到它上次被使用的時間。
金鑰、輪替與 kid 標頭
簽章金鑰應該要能在不中斷服務的情況下輪替,而做到這件事的機制就是 kid 標頭:簽發者標明是哪一把金鑰簽了這個權杖,驗證者則據此查找金鑰,而不是自行假設。用 HS256 時,這代表一份把金鑰識別碼對應到密鑰的小型對照表;用 RS256 或 ES256 時,則代表一份由驗證者抓取並快取的 JWKS 文件。
輪替接著分成三個階段:先發佈新金鑰讓驗證者認得它,再把簽章切換到新金鑰、同時仍接受舊金鑰,最後在所有用舊金鑰簽出的權杖都過期之後才淘汰舊金鑰。省略中間這段重疊期,正是讓例行輪替變成事故的原因。
只要驗證你權杖的服務超過一個,非對稱演算法多出來的設定成本就值得了。用 HS256 時每個驗證者都握有一份同時也能拿來簽章的密鑰,所以任何一個被入侵的服務都能簽出權杖;用 RS256 時驗證者只握有公開金鑰,偽造不了任何東西。
什麼該放進 payload,什麼不該
權杖是一份 bearer 憑證,每個請求都會帶在標頭裡,所以大小是有實際代價的:代理伺服器常把標頭上限設在 8 KB,而臃腫的權杖每次呼叫都得付一次帳。內容請控制在身分本身,加上驗證者需要的少數事實:subject、issuer、audience、到期時間,以及一小組 scope 或角色。
任何易變的東西都不適合放進來。烤進權杖裡的權限從簽發那一刻起就過時了,所以在 10:00 被收回的角色,權杖仍會一路主張到它過期為止。如果這點很重要,那就讓權杖只攜帶身分、由服務自行查詢授權,或者把生命週期縮短到這種過時程度可以接受。
機密資訊則根本不該出現在裡面。payload 是編碼過的,不是加密過的,所以任何拿到權杖的人都能讀到每一項 claim:不要放內部註記,不要放超出接收方所需的個人資料,也不要放金鑰。如果 payload 真的必須保密,那屬於 JWE,是另一份規格、另一套工具。
測試權杖又不外洩任何東西
產生器最有用的地方是製作測試資料:一個已過期的權杖、一個尚未生效的、一個 audience 不對的、一個用錯誤金鑰簽章的。驗證程式這四種都應該測過,而這個領域大部分的錯誤,都是其中某一種被放行了。
請使用測試用的密鑰,絕不要用正式環境的。這和任何憑證的道理相同,只是在這裡更加尖銳:光是權杖加上它的簽章,就足以對密鑰發動離線攻擊。各環境使用不同密鑰,也能防堵一種更隱晦的失誤,也就是在 staging 簽出的權杖竟然在正式環境被接受。
這個頁面上的一切都在瀏覽器裡執行,所以在這裡輸入的內容不會被傳送或儲存。考慮到大家平常會往權杖工具裡貼什麼,這點值得知道;這也正是這裡沒有非對稱演算法的原因:要用 RS256 簽章就得把私鑰貼進網頁裡,而沒有任何工具該向你要這個。
手工權杖被拒絕的常見原因
最常見的是把時間 claim 寫成毫秒。NumericDate 是從 epoch 起算的秒數,所以一個十三位數的 exp 會被讀成幾萬年後的日期,有些函式庫直接拒絕,有些則當成永不過期的權杖接受,兩種都不是你想要的。
其次是 padding。JWT 的各段使用不帶 padding 的 base64url,所以一個各段結尾帶等號的權杖,或是含有加號和斜線而不是減號和底線的權杖,就是用錯字母表編碼的,還沒檢查到簽章就會先失敗。
其餘多半是對不起來。驗證者期待的 audience 差了一條結尾斜線;issuer 寫成 http 而驗證者用的是 https;某台機器的時鐘差了幾分鐘,卻沒有設定容許的時間誤差。當權杖明明能正確解碼卻還是驗證失敗時,先逐欄比對 claim 和驗證端的設定,再去懷疑簽章。
常見問題
- 輸入簽章密鑰安全嗎?
- 密鑰只會被本頁的 JavaScript 使用,不會傳送、儲存或寫入網址,因此分享連結也不會外洩。即便如此,請將正式環境的簽章密鑰視同密碼,測試時請使用臨時值。
- 為什麼只支援 HS256、HS384 與 HS512?
- 它們屬於對稱式演算法,同一組密鑰即可完成簽章與驗證。RS、ES、PS 屬於非對稱式,需要把私密金鑰貼進網頁表單,本工具刻意避免要求這件事。
- iat 與 exp 應該填什麼?
- 兩者都是 NumericDate,單位為自 Unix 紀元起的「秒」而非毫秒。在此選擇有效期限會自動填入正確格式;以毫秒填寫是手寫權杖遭拒最常見的原因。
- 可以加入自訂的標頭欄位嗎?
- 標頭會設為您選擇的演算法加上 typ: JWT。kid 之類的欄位取決於特定的金鑰管理方式,較適合由實際簽發權杖的函式庫加入。
- 這裡產生的權杖可以用在正式環境嗎?
- 不建議。本工具用於測試與除錯。正式權杖應由您的認證服務簽發,並由其管理金鑰輪替、撤銷與宣告驗證。
最後更新:
請提供操作步驟、預期結果及實際結果。請移除機密與個人資料。
