為什麼大多數 OAuth 2.0 服務使用 JWT
本文說明為什麼 JWT 作為存取權杖的格式在 OAuth 2.0 中被廣泛採用,並強調其優點和局限性。
OAuth 2.0 今天被廣泛使用。作為授權服務的核心框架,OAuth 2.0 的主要責任之一是為用戶發放存取權杖。我們注意到,市場上許多 OAuth 服務提供者發放的存取權杖都是 JWT 格式的。
在本文中,我們將介紹什麼是 JWT,以及為什麼它被廣泛採用為 OAuth 2.0 發行的存取權杖的格式。
介紹 JWT
JWT 代表 JSON Web Token,它由 RFC 7519 定義如下:
JSON Web Token (JWT) 是一種緊湊的、URL 安全的方式,用於表示在兩個方之間傳遞的聲明。
這一定義清楚地表明 JWT 是一種在不同方之間傳遞聲明的權杖。
由於 JWT 是在多個方之間傳遞的,因此它們被簽署以確保數據的完整性和真實性。
經過簽署的 JWT 格式如下:
它由三部分組成,以 .
分隔:標頭、有效載荷和簽名。
以下是一個真實世界中的 JWT 範例:
你可以嘗試在 https://jwt.io 上解析:
如圖所示,JWT 的 header
部分包含了有關使用的簽名算法和權杖類型的信息。payload
部分則包含 JWT 攜帶的聲明,而 signature
用於驗證 JWT 的完整性。
現在我們了解了什麼是 JWT 以及其不同部分的含義,接下來我們將解釋為什麼許多 OAuth 授權服務選擇 JWT 作為其存取權杖。
使用 JWT 的優勢
JWT 與傳統的隨機生成字串為基礎的權杖之間的關鍵區別在於 JWT 可以攜帶信息,並能夠通過解碼進行驗證。這些差異帶來了兩個顯著的優勢:
- 資源效率:JWT 可以攜帶有關用戶或會話的信息,消除了頻繁查詢數據庫的需求。這種效率可以減少服務的資源消耗。
- 改善的可用性和擴展性:JWT 減少了對伺服器端狀態管理的依賴。這使得服務更具無狀態性,從而提升了服務的可用性和擴展性。
使用傳統的隨機字串為基礎的權杖時,驗證和身份認證的典型過程如下:
如圖所示,當系統有大量用戶和許多不同的資源伺服器時,可能會對 Auth Server 發送大量權杖驗證請求。
隨著系統的增長,Auth Server 很容易成為瓶頸,對整體服務可用性構成挑戰。
然而,引入 JWT 後,驗證過程改變為:
由於 JWT 可以通過解碼進行驗證,資源伺服器可以驗證 JWT 的完整性,並從中提取用戶信息,無需與 Auth Server 交互(有關 JWT 解碼和驗證的詳情,請參考 Logto 文檔)。
JWT 的局限性
雖然 JWT 在現代軟體架構中提供了顯著的優勢,但也存在需要考慮的局限性。
容易被竊取的有效載荷
如前所述,JWT 由三部分組成:header
、payload
和 signature
。
這些組件是如何生成的?讓我們採用前面範例中的 JWT,演示 JWT 的生成過程:
如上所示的代碼中,JWT 的標頭和有效載荷只是被編碼為 base64 字串。
這意味著只要有人獲得權杖,就可以輕易解碼 JWT 有效載荷的 base64 字串,訪問其攜帶的信息。反之,也相對容易偽造一個有效載荷,並用一個篡改的有效載荷取代原來的 JWT。
雖然 JWT 的有效載荷比較容易被偽造,但需要注意的是,JWT 的簽名部分不能被偽造內容替換,因為這需要秘密的簽名鍵。因此,沒有正確的簽名,JWT 無法通過驗證。
所以,在使用 JWT 時,需要記住以下考量:
- 始終使用 SSL:為了確保 JWT 信息在傳輸過程中不會洩露,必須使用 SSL(安全套接字層)或其繼任者 TLS(傳輸層安全性)來加密傳輸中的數據。
- 避免存儲敏感數據:不建議將敏感數據存儲在 JWT 有效載荷中。如前所述,有效載荷很容易被解碼,應主要包含非敏感的相關聲明。
- 驗證 JWT:在依賴 JWT 包含的信息之前,確保它已通過有效且安全的驗證過程,包括驗證簽名和檢查權杖過期,這有助於防止使用被篡改或未經授權的權杖。
難以撤銷
一般而言,存取權杖通常有一個到期時間。如果存取權杖表現為不包含任何信息的隨機字串,我們可以在 Auth Server 的每次驗證過程中檢查該權杖是否被撤銷。
而對於 JWT,由於其自身包含到期信息,且 JWT 驗證不依賴於 Auth Server,一旦 Auth Server 發行以 JWT 格式的存取權杖,則在其使用期間無法更改該權杖的狀態。
JWT 權杖自然過期後,我們可以使用刷新權杖從授權服務獲取新的 JWT(有關刷新權杖的信息,可以參考 Logto 的博客)。
然而,在某些情況下,如用戶撤銷授權或更改密碼時,需要撤銷已發行尚未到期的權杖,則沒有簡單的解決方案。
有兩種常見的方法來減輕權杖中途撤銷的影響:
- 設置較短的存取權杖到期時間,並依賴權杖刷新機制及時刷新權杖狀態。
由於存取權杖具有較短的到期時間,當用戶發現存取權杖已過期時,他們可以通過刷新權杖從授權服務請求一個新的存取權杖。這樣一來,權杖的狀態可以儘快與後端同步。然而,這種方法會帶來額外的開銷,用戶需要考慮這一點。
- 維護一個存取權杖的撤銷列表,每次驗證期間檢查權杖是否在列表中。
此方法有一定的限制。JWT 的一個優勢是不需要伺服器存儲狀態信息,且 JWT 通常是無狀態的。然而,維護撤銷列表需要有效的存儲和維護,依賴額外的存儲機制。這在本質上犧牲了 JWT 的優勢,並 可能導致性能問題。因此,權杖撤銷機制需要由開發者根據具體用例實施。
總結
在本文中,我們簡要介紹了 JWT,強調了其優勢和局限性。到現在,你應該對 JWT 及其常用場景有更深入的了解。雖然 JWT 本身存在挑戰,但作為 OAuth 2.0 服務中的權杖格式使用時所帶來的優勢遠大於其缺點。
Logto 作為一個快速增長的身份驗證服務也採用了 JWT 作為其存取權杖的格式。它嚴格遵循各種授權和身份驗證協議,使得將身份驗證服務集成到你的產品中變得非常容易。Logto 已正式推出其 SaaS 服務,你可以立即免費試用。