Intro
JWT (JSON Web Token) 是一種基於 JSON 的開放標準(RFC 7519),它定義了一種簡潔(compact)且自包含(self-contained)的方式,用於在雙方之間安全地將訊息作為 JSON 物件傳輸。而這個訊息是經過數位簽章(Digital Signature),因此可以被驗證及信任。可以使用 密碼(經過 HMAC 演算法) 或用一對 公鑰/私鑰(經過 RSA 或 ECDSA 演算法) 來對 JWT 進行簽章。
- RFC 7515 - JSON Web Signature(JWS)
JWT 的簽名標準,包括 Header、Payload 和 Signature,Header 指定了所使用的算法和相關的參數。 - RFC 7516 - JSON Web Encryption(JWE)
加密 JWT Payload 的標準,包括 Header、Public key、IV、Ciphertext 和 Tag,Header 指定了所使用的加密算法和相關的參數。 - RFC 7517 - JSON Web Key(JWK)
用於描述加密和簽章金鑰的 JSON 格式,可以表示對稱式或非對稱式加密、簽章的金鑰。 - RFC 7518 - JSON Web Algorithms(JWA)
定義用於JWS和JWE中的加密、解密和簽名算法的標準 - RFC 7519 - JSON Web Token(JWT)
應用情境
- 授權(Authorization):
這是很常見 JWT 的使用方式,例如使用者從 Client 端登入後取得 JWT,該使用者再次對 Server 端發送請求的時候會夾帶著 JWT (Bearer header),允許使用者存取該 token 有權限的資源。單一登錄(Single Sign On)是當今廣泛使用 JWT 的功能之一,因為它的成本較小並且可以在不同的網域(domain)中輕鬆使用。 - 訊息交換(Information Exchange):
JWT 可以透過公鑰/私鑰來做簽章,讓我們可以知道是誰發送這個 JWT,此外,由於簽章是使用 header 和 payload 計算的,因此還可以驗證內容是否遭到篡改。
Flow
General Usage:
(Reference: Anshul's Blog)
JWT 資料結構與格式
JWS
BASE64URL(UTF8(JWS Protected Header)) || '.' ||
BASE64URL(JWS Payload) || '.' ||
BASE64URL(JWS Signature)
Example code:
header = { "alg": "HS256", "typ": "JWT" }
payload = { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
signature = HMAC-SHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
JWS = base64UrlEncode(header) + '.' + base64UrlEncode(payload) + '.' + base64UrlEncode(signature)
JWE
BASE64URL(UTF8(JWE Protected Header)) || '.' ||
BASE64URL(JWE Encrypted Key) || '.' ||
BASE64URL(JWE Initialization Vector) || '.' ||
BASE64URL(JWE Ciphertext) || '.' ||
BASE64URL(JWE Authentication Tag)
Example code:
header = base64UrlEncode({ "alg": "RSA-OAEP", "enc": "A256GCM" })
key = RSA-OAEP(publicKey, randomKey)
iv = generateRandomIV()
cipherText = AES-256-GCM(plaintext, randomKey, IV)
tag = generateTag(randomKey, IV, ciphertext)
JWE = base64UrlEncode(header) + '.' + base64UrlEncode(key) + '.' + base64UrlEncode(iv) + '.' + base64UrlEncode(cipherText) + '.' + base64UrlEncode(tag)
JWK - JSON Web Key
JWK用於表示加密金鑰的結構與格式,其中使用的加密算法則規範在JWA。
拿 LINE Developer 文件上的 JWK 來做範例:
private.key
example:
{
"alg": "RS256",
"d": "GaDzOmc4......",
"dp": "WAByrYmh......",
"dq": "WLwjYun0......",
"e": "AQ......",
"ext": true,
"key_ops": [
"sign"
],
"kty": "RSA",
"n": "vsbOUoFA......",
"p": "5QJitCu9......",
"q": "1ULfGui5......",
"qi": "2cK4apee......"
}
public.key
example:
{
"alg": "RS256",
"e": "AQ......",
"ext": true,
"key_ops": [
"verify"
],
"kty": "RSA",
"n": "vsbOUoFA......"
}
補充 LINE Message API 的 JWT 驗證應用流程:Developer 產生 Key pair 並提供 JWK 格式的 Public key 給 Channel 到 Developer console 去註冊(Register),public key 註冊完成後會隨機取得
kid
以供 Developer issue channel access token 時帶入 (Signature 利用 Private key 簽發), 以完成身份驗證取得核發的 access token。
SDK 開發套件
PHP
- Firebase JWT: https://github.com/firebase/php-jwt
- Lcobucci JWT: https://github.com/lcobucci/jwt
Python
- PyJWT: https://github.com/jpadilla/pyjwt
- python-jose: https://github.com/mpdavis/python-jose