毫無反應,就是個 JWT (JSON Web Token)
什麼是 JWT?
- 一種基於 JSON 格式,用於傳輸信任資訊的簽章 (signature) 與編碼 (encoding) 技術
- 因此資料可以反解 (decoding) 回去
- 常用於分散式環境下,取代 session 認證,可擴展的解決方案
- 單點認證
- JWT 描述使用者資訊,可達成無狀態 (stateless)
- 單點認證
- e.g.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Session 的問題?
- Server 記憶體消耗
- 擴展困難
- 跨主機間的 session 共享?
- CSRF
JWT 運作流程
https://cdn.auth0.com/content/jwt/jwt-diagram.png
- Server-side 無需保存 users 資料 => 無記憶體消耗
- JWT 本身包含所需的使用資料,可達成 stateless HTTP APIs => 方便擴展
- JWT 的存放可以完全不透過 Cookies => 沒有 CSRF 的可能
JWT 原理
Header
- 描述使用的簽章演算法,並透過 Base64URL 編碼
- 對稱 / 非對稱加密皆可使用,通常使用 HMAC256
Payload
- 描述使用者與提供者所需要的資訊,並透過 Base64URL 編碼
- 避免儲存敏感資料
- 另外有標準特別規範的聲明 (並未硬性要求)
- iss: Issuer,JWT 的簽章者,可驗證是否原本的簽章者簽章
- sub: Subject,此 JWT 底下服務的服務,需要局部或全域唯一 (unique)
- aud: Audience,接收此 JWT 的使用者,一個可被 identify 的 StringOrURI
- exp: JWT 過期時間,此數值必須大於簽章時間,單位為秒
- nbf: 定義在此時間點以前,JWT 都是不可用的
- iat: JWT 的簽章時間
- jti: JWT 的唯一識別,可用於一次性 koken,避免重放攻擊 (replay attack)
Signature
- 將 Header 與 Payload 以
.
相連,然後根據指定的演算法,加上 secret key 簽章- 若是使用非對稱 RSA 加密,則透過 private key 簽章,然後透過 public key 驗證
將 Header、Payload 與 Signature 分別以 .
相連的結果,即為我們產生的 token
注意
- 通常會使用 Base64URL 編碼取代 Base64
- Base64URL 會另外處理瀏覽器 URL 上的特殊符號
- e.g. “+” => “-”, “/” => “_”
- Base64URL 是可反解的,避免儲存敏感資料
- Secret Key 只存在 Server,需妥善保管
- JWT 的產生與驗證皆只在 Server-side 完成
驗證
- 將 Client 傳輸過來的 token,取出 Header 與 Payload 的部份,根據 Header 描述的演算法,配合 secret key 重新運算簽章流程,比較是否與 Signature 相同,相同則表示未經偽造。
- 另外將 Payload 解碼,取出聲明依序驗證(可包含規範與自定的聲明)
- e.g. 驗證 exp 是否有大於當前時間,若否,則失效
使用
- Client 每次請求時,皆會帶上 token 給 Server 驗證
- 正規作法是透過 HTTP 的
Authorization
header,以Bearer ${token}
的形式帶上- e.g.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Bearer
只是描述要以 JWT 的方式驗證,沒有硬性規定,以 Client 與 Server 約定為主
- e.g.
- 亦可透過 GET 的的 query string (較不建議) 或 set cookies (有 CSRF 風險) 的形式達成
JWT demo with koa2
JWT 的繆誤
- 並非加密 (encryption) 機制,資料可被解碼,並且只是單純的驗證資訊是否被竄改
- 因此沒有能力確保資料安全,避免存放敏感資料
- 確保資料安全請用 SSL/TLS
其他
- 根據使用的安全性需求,調整 token 的壽命,或者是使用一次性 token
- jwt.io 有提供 Debugger 與建議的各語言實作套件清單
- node: node-jsonwebtoken