[JWT] JSON Web Token 指南

Intro

JWT (JSON Web Token) 是一種基於 JSON 的開放標準(RFC 7519),它定義了一種簡潔(compact)且自包含(self-contained)的方式,用於在雙方之間安全地將訊息作為 JSON 物件傳輸。而這個訊息是經過數位簽章(Digital Signature),因此可以被驗證及信任。可以使用 密碼(經過 HMAC 演算法) 或用一對 公鑰/私鑰(經過 RSA 或 ECDSA 演算法) 來對 JWT 進行簽章。

Wiki - JSON Web Token

JWT Bytebytego
(Reference: ByteByteGoHq/system-design-101 - Github)

應用情境

  • 授權(Authorization)
    較常見 JWT (JWS) 的使用方式,例如使用者從 Client 端登入後取得 JWT,該使用者再次對 Server 端發送請求的時候會夾帶著 JWT (Bearer header),Server 驗證該 JWT 以提供權限 (可能僅用 key 驗證明文簽章,即 Stateless JWT)。單一登錄 (Single Sign On) 是當今廣泛使用 JWT 的功能之一,優勢為成本較小並且方便跨網域 (domain)。


    (Reference: Anshul's Blog)

  • 訊息交換(Information Exchange)
    JWT (JWS) 可以透過公鑰/私鑰,或者對稱式金鑰來做簽章,以驗證訊息可靠性。或者使用 JWE 實作加密訊息交換。


JWT 資料結構與格式

JWT - Debugger Tool

JWS

JWS Compact Serialization:

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)

JWS JSON Serialization - General & Flattened:

JWE

JWE Compact Serialization

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)

JWE JSON Serialization - General & Flattened


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

Python

JAVA

NodeJS


References

Leave a Reply

Your email address will not be published. Required fields are marked *