解碼一個 JWT access token(存取權杖),指的是把緊湊格式的 header.payload.signature 字串拆成三個部分,並把前兩段——header 與 payload——從 Base64url 編碼的 UTF-8,還原成可讀的 JSON 物件。第三段簽章,只會被檢查它是否符合緊湊格式;它的位元組永遠不會被拿來當成成功驗證過的簽章來解讀,因此解碼出來的 payload,只是這個權杖聲稱了什麼的資訊,並不能證明這個權杖是真實可信的。JSON Web Token(JWT)是一個小型、經過簽署的 JSON 物件,API 與身分識別提供者用它來攜帶關於已登入使用者或用戶端的聲明(claim),而 access token 就是用來授權 API 呼叫的那種特定 JWT。要在本機檢視一個 JWT,可以把它貼進以瀏覽器為基礎的JWT 解碼器;這個工具會在你正在閱讀本文的同一台機器上,執行 Base64url 解碼與 JSON 解析,永遠不會上傳這個權杖,並且會把每一次成功的解碼結果標示為「未經驗證」,避免快速檢視被誤認為是一次安全檢查。

解碼 JWT access token 實際上做了什麼
以緊湊序列化格式呈現的 JSON Web Token,其實就是三段用點號連接起來的 Base64url 編碼字串。header 描述這個權杖使用的簽署演算法,有時也會包含金鑰識別碼;payload 存放發行者想讓接收端服務讀取的聲明;signature 則是用來證明 header 與 payload 在權杖發出之後未曾被更動過的密碼學證明。access token 是 OAuth 2.0 或 OpenID Connect 流程交給用戶端應用程式的那種特定 JWT,讓用戶端可以代表使用者呼叫受保護的 API。解碼一個 JWT,指的是把緊湊格式拿出來,依照點號拆分,再把前兩段轉換回 UTF-8 的 JSON。這個過程不涉及任何密碼學運算;簽章這一段,只會被檢查它是否符合緊湊格式。
RFC 7519 把這種三段式表示法定義為緊湊 JWS 序列化格式。RFC 7519也列出了解碼器可以依名稱辨識的註冊聲明。RFC 4648則定義了這幾段所使用的 Base64url 字元集——也就是 URL 安全版本的 Base64,把「+」換成「-」、把「/」換成「_」,並且通常會省略標準 Base64 裡常見的「=」補齊字元。因此,一個實用的解碼器,必須接受這些替換字元,並拒絕帶有補齊字元的字串,而不是悄悄地接受另一種不同的格式。
為什麼要在本機解碼,而不是貼到隨便一個線上網站
access token 經常攜帶你不想外洩的資訊。即使它不包含密碼,也可能攜帶使用者識別碼、電子郵件、租戶 ID、授權範圍(scope)、角色名稱、工作階段中繼資料,或內部客戶編號。把這串字串傳送給一個不熟悉的網站服務,等同於把鑰匙交給經營這個服務的人、他們串接的分析服務供應商、那個頁面上安裝的瀏覽器擴充功能,以及他們保留的任何日誌記錄。注重隱私的工具做法正好相反:JWT 解碼器完全在瀏覽器中完成解碼,從不為了這個權杖發出任何網路請求,不會去抓取簽署金鑰,不會把副本寫到任何地方,也不需要帳號。這個頁面就是一個單純的靜態介面,只會依照點號拆分字串,並在本機執行 Base64url 解碼與 JSON 解析。
這一點在開發階段與正式環境除錯時同樣重要。一個被貼進聊天訊息串、截圖,或公開貼上網站的權杖,只要還沒過期、且對象(audience)相符,就可以被重放到它原本核發的那個 API 上。在本機解碼,會讓這個權杖只在你保持頁面開啟的期間,顯示在你自己的畫面上,這也讓它適合用來完成每個後端開發者遲早都要做的日常檢視工作。
三步驟解碼一個 JWT Access Token
- 在瀏覽器中開啟 JWT 解碼器頁面,貼上一個標準 header.payload.signature 格式的緊湊 JWT。請確認你貼上的是完整的權杖——三段以兩個點號分隔的 Base64url 字串——不要有多餘的空白、外層的引號,也不要在點號附近夾雜換行字元。
- 選擇「Decode JWT(解碼 JWT)」。頁面會依照點號拆分這個字串,檢查是否恰好有三段,驗證前兩段是否使用未補齊的 RFC 4648 Base64url 字元集,把每一段解碼成 UTF-8,並把結果解析成一個 JSON 物件。第三段只會被檢查它是否符合緊湊的 Base64url 格式;它的位元組永遠不會被拿來當成成功驗證過的簽章來解讀。
- 查看 header 與 payload 面板。解碼器會列出所有存在的 RFC 7519 註冊聲明——發行者、主體、對象、到期時間、生效起始時間、發行時間,以及 JWT ID——並與原始 JSON 並列顯示,讓你也能看到應用程式使用的任何私有聲明名稱。這個頁面會把每一次成功的解碼,標示為「未經驗證」;使用完畢後,請關閉頁面或清空輸入內容,避免這個權杖持續顯示在畫面上。
如果工具回報的是錯誤而不是解碼結果,最常見的原因包括:段數不對(少了一段或多了一段)、出現不屬於 URL 安全字元集的補齊 Base64 字元、header 或 payload 不是合法的 JSON,或是某一段解碼出來的內容不是有效的 UTF-8。請回到發行這個權杖的應用程式修正原始權杖,再重新嘗試——不要試圖手動修補一個權杖。
解讀解碼後的 header 與 payload
header 幾乎永遠是一個很小的物件,裡面有一個 alg 欄位,用來指出簽署演算法的名稱——HS256、RS256、ES256 等等——並可能附帶 typ、kid 或 cty 欄位。如果 alg 的值是「none」,代表這個權杖沒有加密保護,第三段是空的;即使成功解碼,也應該把這種權杖視為不可信任。payload 則是應用程式專屬聲明與標準聲明所在的地方。
| 聲明 | 完整名稱 | 在 access token 中的意義 |
|---|---|---|
| iss | Issuer(發行者) | 核發這個權杖的一方;應該與你 API 的發行機構一致。 |
| sub | Subject(主體) | 這個權杖所代表的主體——通常是使用者 ID 或服務帳號。 |
| aud | Audience(對象) | 預期的接收方;可以是一個字串或字串陣列,應該包含你的 API 識別碼。 |
| exp | Expiration time(到期時間) | 以 Unix 秒數表示,超過這個時間之後,就不應該再接受這個權杖。 |
| nbf | Not before(生效起始時間) | 以 Unix 秒數表示,在這個時間之前,不應該接受這個權杖。 |
| iat | Issued at(發行時間) | 以 Unix 秒數表示這個權杖核發的時間。 |
| jti | JWT ID | 這個權杖的唯一識別碼;有助於防範重放攻擊。 |
自訂聲明會與註冊聲明並列出現,可以攜帶發行者選擇放進去的任何內容——租戶、角色、授權範圍、內部旗標,或功能開關。解碼器會把它們原封不動地顯示在原始 payload 中,讓它們保持可見,但不會賦予它們任何特殊意義。JWT 也允許一個私有命名空間,用來放置以註冊前綴開頭、但最終對應到應用程式專屬值的聲明;在發行服務對這些聲明做出說明之前,應該把它們視為不可信任。
解碼 vs. 驗證:為什麼可讀的 payload 不是證明
解讀 access token 時最常見的錯誤,就是把解碼出來的 JSON 當成這個權杖有效的證據。解碼與驗證是兩個不同的操作。解碼是把前兩段從 Base64url 轉換成 JSON;驗證則是拿已知的金鑰去檢查簽章、確認發行者與對象是否與你的服務相符、執行到期政策,然後才決定要不要接受這個權杖。本機解碼器只能做到前面那一半。
這代表一個成功解碼的 access token,仍然可能是偽造的、已經過期、是核發給另一個應用程式的、是用你的服務不信任的金鑰簽署的,或是登出之後被重放的。它也可能是一個簽章已經在另一個系統中被檢查過、現在只是留在某個開發者剪貼簿裡的權杖。可讀的 payload,描述的是這個權杖聲稱持有者是誰;它並不能證明持有者真的就是權杖所聲稱的那個人。只要牽涉到信任問題,就應該在核發這個權杖的應用程式的驗證函式庫與金鑰管理流程中執行驗證,使用該服務實際強制執行的發行者、對象、演算法、金鑰,以及時鐘偏移容許政策。
檢視 Access Token 中的時間戳記聲明
exp、nbf 與 iat 這幾個聲明,都是 NumericDate 數值:也就是自 Unix 紀元起算的秒數,不計算閏秒。由於在開發者主控台裡,直接看整數秒數並不容易一眼看懂,JWT 解碼器會把每一個存在的時間戳記,同時顯示原始數值與 ISO 8601 字串,這樣一個十位數的數字,一眼就能看出對應的 UTC 時間點。這段 ISO 文字只是幫助閱讀,並不是一種保證——這個時間戳記是否可以接受,取決於發行系統、它設定的時鐘偏移容許範圍、它預期的對象,以及該服務所套用的驗證政策。
| 聲明 | 型別 | 頁面顯示的內容 | 你仍然需要自行檢查的事項 |
|---|---|---|---|
| exp | NumericDate | 原始秒數與 ISO 時間戳記 | 發行系統的時鐘偏移容許範圍與到期政策,是否仍然認定它有效 |
| nbf | NumericDate | 原始秒數與 ISO 時間戳記 | 在發行者的時鐘偏移容許範圍下,目前時間是否已經超過 nbf |
| iat | NumericDate | 原始秒數與 ISO 時間戳記 | 這個權杖的存在時間長短,是否會影響應用程式的政策 |
這就是為什麼一個能乾淨解碼的 access token,仍然可能在 API 閘道被拒絕的原因:閘道會強制執行時間戳記檢查,而你本機的解碼器不會。請把你讀到的時間戳記數值,當成是關於發行者意圖的資訊,而不是關於這個權杖目前是否可被接受的最終判定。如果需要在 JWT 情境之外做交叉核對,Unix 時間戳記轉換器可以把同一個 NumericDate,轉換成 UTC、你的本地時區,或 ISO 8601 字串,而不會把這個數值傳送到任何地方。