什麼是令牌?
在介紹不透明令牌之前,了解什麼是令牌很重要:
令牌用於在各方之間表示和傳輸安全信息,它們支持互聯網上大多數在幕後發生的 認證 (Authentication) 和 授權 (Authorization) 過程。網絡服務中最流行的兩種類型的令牌是 JSON Web Token (JWT) 和不透明令牌。
什麼是不透明令牌?
不透明令牌是你無法訪問的專有格式的令牌,通常包含一些標識符以指向服務器的持久存儲中的信息。
不透明令牌是一種令牌的形式, 訪問令牌 (access tokens) 和 刷新令牌 (refresh tokens) 可以以不透明令牌的形式存在。不透明令牌的格式由其發行者決定,通常是一串數字和/或字符,用於幫助發行者在數據庫中檢索和識別某些信息。以下是一個不透明令牌的例子:
M-oxIny1RfaFbmjMX54L8Pl-KQEPeQvF6awzjWFA3iq
另一方面,JWT 是另一種常見的令牌格式。它是一個包含所有聲明和信息的 JSON 字符串,並附有發行者的簽名。默認情況下,它不加密,但可以使用 JSON 網路加密 (JSON Web Encryption, JWE) 標準進行加密。即使 JWT 通常未加密,它的安全性也不會受到影響——簽名的存在確保了令牌內容的完整性,允許完全信任 JWT 中的數據。
與 JWT 不同,JWT 包含所有必要的信息,可以直接在受保護的資源處驗證,不透明令牌不能由資源直接驗證。相反,它們需要由不透明令牌的發行者(通常是 授權伺服器 (Authorization server) )進行驗證。這個驗證過程通常被稱為 權杖內省 (Token introspection) 。
什麼是 JWT?
與不透明令牌相反,JWT 是一種自包含的、無狀態的令牌,以結構化和可讀的格式攜帶信息。
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 和一個秘密密鑰使用指定的算法生成的。這個簽名用於驗證令牌的完整性,確保它未被篡改。
JWTs 被廣泛使用,因為它們可以由客戶端或任何服務在本地驗證,而無需與授權服務器交互。這使得 JWTs 對於分佈式系統特別有效,其中多個服務可能需要獨立驗證令牌的真實性。
然而,這種便利也伴隨著確保令牌的聲明不被過度暴露的責任,因為它們對任何擁有令牌的人都是可見的。此外,JWTs 通常是短期有效的,過期時間包含在令牌的聲明中,以確保令牌不會無限期有效。
不透明訪問令牌驗證
不透明訪問令牌通過將其發送回授權服務器進行驗證。授權服務器維護已發行令牌的狀態,並可以根據其內部存儲確定令牌的有效性。
- 客戶端向授權服務器請求訪問令牌。
- 授權服務器發行不透明令牌。
- 客戶端在標頭中發送帶有不透明令牌的資源訪問請求。
- 資源提供者向授權服務器發送令牌內省請求以驗證令牌。
- 授權服務器響應令牌信息。
JWT 訪問令牌驗證(離線)
JWT 訪問令牌可以由擁有令牌公鑰的客戶端或任何服務離線驗證。
- 資源提供者預先從 OpenID Connect (OIDC) 發現 (Discovery) 獲取授權服務器的公鑰。公鑰用於驗證令牌的簽名並確保其完整性。
- 客戶端向授權服務器請求訪問令牌。
- 授權服務器發行 JWT 令牌。
- 客戶端在標頭中發送帶有 JWT 令牌的資源訪問請求。
- 資源提供者使用從授權服務器獲得的公鑰解碼並驗證 JWT 令牌。
- 資源提供者根據令牌的有效性授予訪問權限。
OIDC 中的使用案例
在 OIDC ( OpenID Connect (OIDC) ) 的背景下,不透明令牌和 JWT 用於不同的目的並在不同的場景中使用。
不透明令牌
- 用戶資料檢索:
默認情況下,當客戶端請求訪問令牌而未指定資源並包含 openid
範圍時,授權服務器發行不透明訪問令牌。此令牌主要用於從 OIDC /oidc/userinfo
端點檢索用戶資料信息。在收到帶有不透明訪問令牌的請求後,授權服務器檢查其內部存儲以檢索相關的授權信息並驗證令牌的有效性,然後響應用戶資料詳細信息。
- 刷新令牌交換:
刷新令牌設計為僅在客戶端和授權服務器之間交換,無需與資源提供者共享。因此,刷新令牌通常以不透明令牌的形式發行。當當前訪問令牌過期時,客戶端可以使用不透明刷新令牌獲取新的訪問令牌,確保持續訪問而無需重新驗證用戶。
JWTs
- ID 令牌:
在 OIDC 中,ID 令牌是一個包含用戶信息的 JWT,用於驗證用戶。通常與訪問令牌一起發行,ID 令牌允許客戶端驗證用戶的身份。例如:
// 解碼的 ID 令牌 payload
{
"iss": "<https://auth.wiki>",
"sub": "1234567890",
"aud": "client_id",
"exp": 1630368000,
"name": "John Doe",
"email": "[email protected]",
"picture": "<https://example.com/johndoe.jpg>"
}
客戶端可以驗證 ID 令牌以確保用戶的身份,並提取用戶信息以進行個性化或授權目的。ID 令牌僅供一次性使用,不應用於 API 資源授權。
- API 資源訪問(使用訪問令牌):
當客戶端請求帶有特定 資源指示器 (Resource indicator) 的訪問令牌時,授權服務器發行用於訪問該資源的 JWT 訪問令牌。JWT 包含資源提供者可用於授權客戶端訪問的聲明。例如:
// 解碼的 JWT 訪問令牌 payload
{
"iss": "<https://auth.wiki>",
"sub": "1234567890",
"aud": "<https://api.example.com>",
"scope": "read write",
"exp": 1630368000
}
資源提供者可以通過檢查聲明來驗證請求:
iss
:確認令牌是由受信任的授權服務器發行的。sub
:識別與令牌相關的用戶。aud
:確保令牌是針對特定資源的。scope
:驗證授予用戶的權限。