繁體中文(香港)
  • auth
  • authentication
  • oauth
  • oidc
  • identity

為什麼大多數 OAuth 2.0 服務使用 JWT

本文解釋了為什麼 JWT 被廣泛採用為 OAuth 2.0 存取權杖的格式,並強調其優勢和限制。

Yijun
Yijun
Developer

OAuth 2.0 是當今廣泛使用的。作為授權服務的核心框架,OAuth 2.0 的一個主要職責是為用戶發行存取權杖。我們注意到市場上許多 OAuth 服務提供商發行的存取權杖都是 JWT 格式。

在本文中,我們將介紹 JWT 是什麼以及為什麼它被大量採用為 OAuth 2.0 所發行的存取權杖格式。

JWT 簡介

JWT 代表 JSON Web Token,其定義在 RFC 7519 中如下:

JSON Web Token (JWT) 是一種緊湊、安全的方式,用於在兩個實體之間傳遞聲明。

該定義清楚表明 JWT 是用於在不同實體之間傳遞聲明的符號。

因為 JWT 通過多個實體傳遞,它們被簽名以確保數據的完整性和真實性。

簽名的 JWT 具有以下格式:

它由三個部分組成,中間以 . 分隔:標頭、有效負載和簽名。

以下是一個實際的 JWT 示例:

你可以在 https://jwt.io 上嘗試解析:

在 jwt.io 中解碼 JWT

如圖所示,JWT 的 header 部分包含有關簽名算法的資訊以及符號類型。payload 部分包含 JWT 所攜帶的聲明,而 signature 用於驗證 JWT 的完整性。

現在我們了解了 JWT 是什麼以及其不同部分的含義,讓我們接下來解釋為什麼許多 OAuth 授權服務選擇 JWT 作為其存取權杖。

使用 JWT 的好處

JWT 與傳統隨機生成的字符串型權杖的主要區別在於 JWT 能夠攜帶資訊,並可以通過解碼進行驗證。這些差異帶來了兩個顯著的優勢:

  • 資源效率:JWT 可以攜帶有關使用者或會話的資訊,消除了頻繁數據庫查找的需求。這種效率可以減少服務的資源消耗。
  • 提高可用性和可擴展性:JWT 減少了對服務端狀態管理的依賴。這讓服務更加無狀態,增強了其可用性和可擴展性。

使用傳統隨機字符串型權杖時,驗證和身份認證的典型過程如下所示:

如圖所示,當系統擁有大量用戶和許多不同的資源伺服器時,可能會對授權伺服器產生大量權杖驗證請求。

隨著系統的增長,授權伺服器很容易成為瓶頸,對整體服務的可用性構成挑戰。

然而,引入 JWT 後,驗證過程改為:

由於 JWT 能通過解碼進行驗證的特徵,資源伺服器能直接驗證 JWT 的完整性並從中提取用戶資訊,而無需與授權伺服器互動(有關 JWT 的解碼和驗證詳細資訊,可參考 Logto 文件)。

JWT 的限制

雖然 JWT 在現代軟件架構中提供了顯著的優勢,但它們也有一些需要考慮的限制。

容易被窺探的有效負載

如前所述,JWT 由三部分組成:headerpayloadsignature。 這些組件是如何生成的呢?讓我們以先前的 JWT 示例來演示 JWT 的生成過程:

如上面的代碼所示,JWT 的標頭和有效負載僅被編碼為 base64 字符串。

這意味著,只要有人可以访问到權杖,他們就可以輕鬆解碼 JWT 有效負載的 base64 字符串,並訪問其攜帶的資訊。反之,也相對容易偽造一個有效負載,並用其替換原始 JWT 的有效負載。

雖然可以相對容易地偽造 JWT 的有效負載,但需要注意的是,JWT 的簽名部分無法用偽造的內容替代,因為需要秘密簽名密鑰。因此,沒有正確的簽名,JWT 無法通過驗證。

所以,使用 JWT 時,需要考慮以下幾點:

  1. 始終使用 SSL:為了確保 JWT 資訊在傳輸過程中不會被洩露,使用 SSL(Secure Sockets Layer)或其後繼者 TLS(Transport Layer Security)加密傳輸中的數據是必須的。
  2. 避免存儲敏感數據:不建議在 JWT 有效負載中存儲敏感數據。正如先前提到的,有效負載可以輕易解碼,應主要包含非敏感的相關聲明。
  3. 驗證 JWT:在依賴 JWT 所包含的資訊之前,確保其已通過有效和安全的驗證過程,包括驗證簽名和檢查權杖的到期時間。這有助於防止使用被篡改或未授權的權杖。

難以撤銷

一般來說,存取權杖通常具有到期時間。如果存取權杖以不包含任何資訊的隨機字符串表示,我們可以在每次驗證中檢查權杖是否已被撤銷。

至於 JWT,由於 JWT 本身包含到期信息,並且其驗證不依賴於授權伺服器,一旦授權伺服器以 JWT 格式發放存取權杖,在其使用過程中無法更改權杖的狀態。

在 JWT 權杖自然過期之後,我們可以使用刷新權杖從授權伺服器獲得新的 JWT(可參考 Logto 的博客 獲取有關刷新權杖的信息)。

然而,在某些情況下,如用戶撤銷授權或更改密碼時,你需要撤銷已發放但尚未過期的權杖,這時則沒有直接的解決方案可用。

有兩種常用的方法來緩解中途撤銷權杖的影響:

  1. 設置更短的存取權杖到期時間,並依賴權杖刷新機制迅速更新權杖的狀態。

由於存取權杖具有更短的到期時間,當用戶發現該權杖已過期時,可以通過授權服務的刷新權杖請求新的存取權杖。這樣,用戶端的權杖狀態可以盡快與後端同步。不過,這種方法會帶來額外的開銷,需要用戶考慮。

  1. 維護一個存取權杖撤銷列表,在每次驗證時檢查權杖是否在列表中。

此方法有一定的限制。使用 JWT 的優勢之一是服務器不需要存儲狀態信息,且 JWT 通常是無狀態的。然而,維護撤銷列表需要有效的存儲和維護,依賴於額外的存儲機制。這本質上犧牲了 JWT 的優勢,可能導致性能問題。因此,權杖撤銷機制需要開發人員根據其具體用例進行實施。

總結

在本文中,我們簡要介紹了 JWT,並突出其優勢和限制。到現在為止,你應該對 JWT 及其常見的使用場景有更深入的理解。雖然 JWT 存在挑戰,但在 OAuth 2.0 服務中作為權杖格式的優勢遠大於其缺點。

Logto 作為一家快速增長的身份認證服務,也採用 JWT 作為其存取權杖的格式。它嚴格遵循各種授權和身份認證協議,使其可以非常容易地將身份認證服務集成到你的產品中。Logto 已正式推出其 SaaS 服務,你可以免費試用。