---
# System prepended metadata

title: JWT 筆記
tags: [前端]

---

## 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/)
