## JWT 筆記 - JWT 為 JSON Web Tokens 的縮寫,於 [RFC 7519 開放標準](https://datatracker.ietf.org/doc/html/rfc7519) 中,它定義了一種簡易且穩定的交換格式用以表示 **身份驗證** 與 **授權數據** 等資料,其主要結構包含 Header、Payload、Signature 三個部份。 - JWT 屬於 Access Token 眾多格式中的其中一種。 - 前端於呼叫 API 時,會將 Token 夾帶於 Header 的 **Authorization** 欄位上,以利後台伺服器進行身份驗證。 :::info **[RFC 6749 開放標準](https://datatracker.ietf.org/doc/html/rfc6749)**: 即 OAuth 2.0,定義了 Client 如何取得 Access Token 的方法,但只定義了抽象的概念。 **[RFC 6750 開放標準](https://datatracker.ietf.org/doc/html/rfc6750)**: 定義了 Barear Token 的用法。 ::: :::info :bulb: **RFC (Request for Comments)**,翻譯為 **意見請求、意見徵求、請求評論**,由網際網路任務工程組(IETF)發布的一系列備忘錄,內容包含忘記網路相關資訊、UNIX 與網際網路社群的軟體檔案,目前由 **網際網路協會 (ISOC)** 發行。 :bulb: 本來是用來紀錄 ARPANET 開發的非正式文件,最終演變為紀錄 **網際網路規範、協定、過程等的標準檔案**。 ::: 後台以 JWT 實作驗證機制: - 後台身份驗證成功後會發給前端 JWT 格式的 token 憑證用以後續透過 API 存取資料(前端會在呼叫 API 時帶在請求 header)。 - 後續收到 Token 只需用金鑰進行解析與驗證,原則上根據安全性原則儲存於瀏覽器的 token 仍需要加密。 :::success :bulb: cookie-base vs session-base: ``` 1. 大小限制:根據 RFC 2965 定義,一個 cookie 僅有 4096 bytes (4 KB) 大小, 一個 domain 至多 20 個 cookies。 2. 佔據網路流量:由於 cookie 攜帶完整資料,故當資料越多則請求 越大,會影響傳輸速度, 3. Cookies 資料可被使用者竄改:由於 Cookies 存在 browser 中, 所以使用者可透過瀏覽器查看 cookies 的資料以及其結構,當使用者 任意竄改 cookies 的資料時可能會導致資料外洩或系統流程出錯。 4. cookie 會將帳密等機敏資料存於用戶端,駭客可輕易取得故不安全,且不可跨域。 ``` :bulb: 在實務上有兩種比較主流的登入機制實作方式,分別為 **session-based** 和 **token-based**,主要差異是 <font color='orange'>**儲存登入資訊的方式**</font>。 :bulb: 在 session-based 機制中,使用瀏覽器內建的 cookie 儲存 session id,伺服端將使用者資料儲存於 session database 進行驗證與管理。(不適用於 API based 的伺服器) :bulb: 而 **前後端分離** 的情境較常採用 **token-based 機制**,在此機制中,後端伺服器發出憑證 (token) 後,前端自行決定如何儲存 token。 - **Basic Token**: 用於網域上的防護,帳密資料僅以 base64 編碼,<font color="red">用於 **內網** 等安全的網域</font>。 - **Bearer Token**: 針對 protected resource 的存取,<font color="red">主要還是使用在 OAuth 2.0 上頭,且一定要在 **TLS 環境 (HTTPS)** 使用</font>。 ![image](https://hackmd.io/_uploads/rk92LBDzA.png) ::: ### JWT 組成結構 ![image](https://hackmd.io/_uploads/ryZMdBPGC.png) - **Header**:標記 token 的 **類型 (typ)與雜湊函式名稱 (alg)**。(Base64URL 編碼機制) - **Payload**:要攜帶的資料,例如 user_id 與時間戳記,也可以指定 token 的過期時間。(Base64URL 編碼機制) - **Signature**:組合 **Header.Payload** 與 **密鑰 (secret key)** 進行雜湊,產生一組**不可反解的亂數**,當成簽章,用來驗證 JWT 是否經過篡改。 :::success :bulb: 以 Bearer Token 的方式帶在請求 Header 的 **Authorization 欄位**,格式為: Bearer {JWT Token} ::: :::success :bulb: 一般由 token-based 後台所發出的訪問憑證 (Access Token) 組成如下: 唯一id(UID) + 時間戳記(Time stamp) + 簽名(signature) :bulb: JWT 只是 Access Token 其中的一種格式。 ::: :::info :bulb: OAuth 2.0 (即 RFC 6749) 定義了 Client 如何取得 Access Token 的方法。 :bulb: 然而在 RFC 6749 裡面只定義**抽象的概念**,細節如 Access Token 格式、怎麼傳到 Resource Server ,以及 Access Token 無效時, Resource Server 怎麼處理,都沒有定義。所以在 RFC 6750 另外定義了 Bearer Token 的用法。 Client 向 Resource Server 出示 Access Token 的方式: 1. 放在 HTTP Header 裡面 2. 放在 Request Body 裡面(Form 之類的) **前提條件:** 2.1. Header 要有 **Content-Type: application/x-www-form-urlencoded**。 2.2. Body 格式要符合 W3C HTML 4.01 定義 application/x-www-form-urlencoded。 2.3. Body 只能有一個 part,<font color='red'>**不可以是 multipart**</font>。 2.4. Body 要編碼成 <font color='red'>**只有 ASCII chars** </font>的內容。 2.5. Request method 必須是一種有使用 request-body 的,也就是說 <font color='red'>**不能用 GET**</font>。 * 即表單,但不可以上傳檔案(multipart/form-data: :x: ) 4. 放在 URI 裡面的一個 Query Parameter <font color='red'>**(不建議)**</font> ::: 參考網址: 1. [RFC 7519](https://www.rfc-editor.org/rfc/rfc7519.html) 2. [什麼是JWT?認識 JSON Web Token 認證機制](https://tw.alphacamp.co/blog/jwt-json-web-token) 3. [淺談 Authentication 上集:Cookie 與 Session 介紹](https://vicxu.medium.com/authentication-%E9%82%A3%E4%BA%9B%E5%B0%8F%E4%BA%8B%E4%B8%8A%E9%9B%86-cookie-%E8%88%87-session-%E4%BB%8B%E7%B4%B9-1da2d413afa2) 4. [OAuth 2.0 筆記 (6) Bearer Token 的使用方法](https://blog.yorkxin.org/posts/oauth2-6-bearer-token/)