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)
(Reference: ByteByteGoHq/system-design-101 - Github)
應用情境
-
授權(Authorization):
較常見 JWT (JWS) 的使用方式,例如使用者從 Client 端登入後取得 JWT,該使用者再次對 Server 端發送請求的時候會夾帶著 JWT (Bearer header),Server 驗證該 JWT 以提供權限 (可能 Server 僅用一組 key 驗證明文簽章,即 Stateless JWT)。單一登錄 (Single Sign On) 是當今廣泛使用 JWT 的功能之一,優勢為成本較小並且方便跨網域 (domain)。
(Reference: Anshul's Blog) -
訊息交換(Information Exchange):
JWT (JWS) 可以透過公鑰/私鑰,或者對稱式金鑰來做簽章,以驗證訊息可靠性。或者使用 JWE 實作加密訊息交換。
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 Public Key for Asymmetric cryptography ) || '.' ||
BASE64URL(JWE Initialization Vector) || '.' ||
BASE64URL(JWE Ciphertext) || '.' ||
BASE64URL(JWE Authentication Tag)
Example code:
header = base64UrlEncode({ "alg": "RSA-OAEP", "enc": "A256GCM", "kid": "5saf8g" })
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