不透明令牌與 JWT
了解不透明令牌與 JWT 的差異、它們的使用情況,以及在 OIDC 基於系統中如何驗證它們。
在 Logto 作為一個基於 OIDC 的綜合 CIAM 平台中,授權令牌在保護用戶互動和管理資源訪問中起著關鍵作用。在用於授權的各種令牌類型中,不透明令牌和 JWT(JSON Web Tokens)是最重要的。
我們從社群收到了一些問題,如:不透明令牌和 JWT 之間的區別是什麼?為什麼我無法解碼收到的訪問令牌,並且為什麼令牌長度看起來很短?這篇部落格文章旨在釐清這些概念並幫助你了解不透明令牌與 JWT 之間的區別、它們的使用情況,以及在處理它們時會遇到不同行為的原因。
什麼是不透明令牌?
不透明令牌是一種訪問令牌,正如其名字所示,對於客戶端或任何外部方是不可透明的。這意味著令牌本身不攜帶關於用戶或授權的任何可讀信息。
當你收到不透明令牌時,它通常顯示為一個看似隨機的字符字符串,嘗試解碼它將不會產生有意義的數據。
這裡有一個不透明令牌的例子:
由於令牌的實際內容僅為發行它的授權伺服器所知,因此,要驗證不透明令牌,客戶端必須將其返回給伺服器,然後伺服器驗證其真實性並確定相關的權限。這種方法確保敏感信息保持隱藏,提供了一層額外的安全性,但也需要額外的伺服器通信來驗證令牌。
優點:
- 安全:不透明令牌不暴露任何敏感信息給客戶端。令牌的內容僅為授權伺服器所知。
- 可撤銷:由於令牌存儲在伺服器上,且唯一驗證方法是通過授權伺服器上的 introspection 端點,伺服器可以輕鬆撤銷令牌以防止未經授權的訪問。
- 小尺寸:不透明令牌通常比 JWT 短小,這對於性能和存儲考量有利。
缺點:
- 有狀態:不透明令牌要求授權伺服器維持狀態以驗證令牌,這可能引入附加的複雜性和開銷。
- 性能:驗證令牌所需的額外伺服器通信可能會影響性能,特別是在高流量場景中。
什麼是 JWT?
與不透明令牌相反,JWT(JSON Web Token)是一種自包含的、無狀態的令牌,承載信息以結構化和可讀格式表達。
JWT 由三部分組成:header
,payload
,和 signature
,每個部分都以 Base64URL 編碼。
這裡有一個 JWT 的例子:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
header
包含有關令牌類型和用於簽名的算法的信息。例如,{"alg": "HS256", "typ": "JWT"}
。payload
區段包含聲明—關於用戶或授權的信息片段,如用戶ID、到期時間和範圍。由於這些數據是編碼的但未加密,任何擁有令牌的人都可以解碼以查看聲明,但無法在不使簽名失效的情況下更改它。根據規範和授權伺服器配置,可以在payload
中包括各種聲明,這賦予令牌其自包含的特性。例如,{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
。signature
是通過使用指定的算法結合header
,payload
和密鑰來生成的。這個簽名用於驗證令牌的完整性並確保它沒有被篡改。
由于它們可以由客戶端或任何服務在本地驗證,而無需與授權服務器互動,JWT 得到了廣泛使用。這使得 JWT 對於分布式系統特別高效,其中多個服務可能需要獨立驗證令牌的真偽。
然而,這種便利也帶來了確保令牌聲明未過度暴露的責任,因為它們對任何有權訪問令牌的人都是可見的。此外,JWT 通常是短命的,到期時間包含在令牌的聲明中,以確保令牌不會無限期有效。
優點:
- 無狀態:JWT 是自包含的,無需伺服器端狀態即可驗證。
- 跨服務兼容性:JWT 可以輕鬆在不同服務之間共享和驗證,使其對於分布式系統理想。
- 可擴展:JWT 的 payload 可以包含自定義聲明,允許靈活的授權和信息共享。
- 標準:JWT 令牌遵循一個良好定義的標準(RFC 7519),使其廣泛支持和可互操作。
缺點:
- 暴露:JWT 中的聲明對任何擁有該令牌的人都是可見的,因此不應在 payload 中包括敏感信息。
- 大尺寸:由於攜帶附加的信息,JWT 可以比不透明令牌更大,這可以影響性能和存儲考量。JWT 令牌中的聲明應保持在最小以減少令牌大小。
- 撤銷複雜性:由於 JWT 是無狀態的,通常在一段時間內有效,且沒有內置的令牌撤銷機制,這意味著被危及的令牌可能會在失效前一直有效。
不透明訪問令牌驗證
不透明訪問令牌通過將其發送回授權伺服器進行驗證。授權伺服器維持已發送令牌的狀態並可以根據其內部存儲來確定令牌的有效性。
- 客戶端向授權伺服器請求訪問令牌。
- 授權伺服器發放不透明令牌。
- 客戶端在 header 中發送不透明令牌與資源訪問請求。
- 資源提供者向授權伺服器發送令牌 introspection 請求以驗證令牌。
- 授權伺服器回應令牌信息。
JWT 訪問令牌驗證(線下)
JWT 訪問令牌可以由擁有令牌公鑰的客戶端或任何服務線下驗證。
- 資源提供者預取授權伺服器的公開密鑰,這個密鑰用於驗證令牌的簽名並確保其完整性。
- 客戶端向授權伺服器請求訪問令牌。
- 授權伺服器發放 JWT 令牌。
- 客戶端在 header 中發送 JWT 令牌與資源訪問請求。
- 資源提供者使用從授權伺服器獲取的公鑰解碼並驗證 JWT 令牌。
- 資源提供者根據令牌的有效性授權訪問。
OIDC 中的使用案例
在 OIDC(OpenID Connect)的上下文中,不透明令牌和 JWT 用於不同的目的並在不同的情境中使用。
不透明令牌
- 用戶資料檢索:
默認情況下,當客戶端在沒有指定資源的情況下請求訪問令牌並加入 openid
範圍時,授權伺服器發放不透明訪問令牌。此令牌主要用於從 OIDC /oidc/userinfo
端點檢索用戶資料信息。收到帶有不透明訪問令牌的請求後,授權伺服器會檢查其內部存儲以檢索相關的授權信息並驗證令牌的有效性,然後才會回應用戶資料詳細信息。
- 刷新令牌交換:
刷新令牌設計為僅在客戶端與授權伺服器之間交換,而不需要與資源提供者共享。因此,刷新令牌通常以不透明令牌形式發行。當當前訪問令牌到期時,客戶端可以使用不透明刷新令牌來獲取新的訪問令牌,保證持續訪問,而無需重新驗證用戶。
JWTs
- ID 令牌:
在 OIDC 中,ID 令牌是一個包含用戶信息的 JWT,用於驗證用戶。通常與訪問令牌一起發行,ID 令牌允許客戶端驗證用戶的身份。例如:
客戶端可以驗證 ID 令牌以確保用戶的身份並提取用戶信息以用作個性化或授權目的。ID 令牌僅供一次性使用,不應用於 API 資源授權。
- API 資源訪問:
當客戶端請求具有特定資源指標的訪問令牌時,授權伺服器會發放用於訪問該資源的 JWT 訪問令牌。JWT 包含資源提供者可以用於授權客戶端訪問的聲明。例如:
資源提供者可以通過驗證聲明來驗證請求:
iss
: 確認令牌由受信授權伺服器發行。sub
: 識別與該令牌相關的用戶。aud
: 確保令牌旨在針對特定資源。scope
: 驗證授予用戶的權限。
結論
總之,不透明令牌和 JWT 在基於 OIDC 的系統中有不同的用途,不透明令牌提供了一種安全和有狀態的授權方法,而 JWT 則提供了一種自包含和無狀態的替代方案。了解這些令牌類型之間的區別及其使用情況,對於在你的應用中設計安全和高效的身份驗證和授權機制是至關重要的。
在 Logto 中探索更多訪問令牌功能: