---
# System prepended metadata

title: OAuth、JWT、OWASP top10
tags: [RD1]

---

# OAuth、JWT、OWASP top10

###### tags: `RD1`

:::spoiler 目錄
[TOC]
:::

## OAuth

### 關於 Open Authorization
是一種**授權**給第三方服務的開放標準，
在使用者不提供密碼的情況下，令第三方服務可以存取使用者(特定範圍內)的帳戶資訊

### 歷史
* 2006:  Twitter 的開發者首倡
* 2007:  OAuth Core 1.0
* 2010:  OAuth 1.0   Protocol 協定
* 2012:  OAuth 2.0   Framework 框架
    * 特點：授權流程標準化，提高安全性並得到廣泛採用（如fb google）

OAuth2.0 與 1.0 互不相容，在2.0框架中可以包涵很多協定來做規範

### 抽象概念流程圖

```
+--------+                               +---------------+
|        |--(A)- Authorization Request ->|   Resource    |
|        |                               |     Owner     |
|        |<-(B)-- Authorization Grant ---|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(C)-- Authorization Grant -->| Authorization |
| Client |                               |     Server    |
|        |<-(D)----- Access Token -------|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(E)----- Access Token ------>|    Resource   |
|        |                               |     Server    |
|        |<-(F)--- Protected Resource ---|               |
+--------+                               +---------------+

                Figure 1: Abstract Protocol Flow
```
#### 角色解說


| 角色 | 說明 | 比如 |
| -------- | -------- | -------- |
| Resource Owner  | 資源擁有者  | 擁有fb帳號的你我   |
| Resource Server  | 資源伺服器  | 掌握使用者資料的fb  |
| Client | 用戶端（第三方服務） | 需要存取你fb資料作為資源的程式 |
| Authorization Server | 授權伺服器 | fb的獨立授權伺服器 |

#### 流程解說
**A** . 用戶端向資源擁有者請求授權

**B** . 資源擁有者授權用戶端可以去取得 Access Token 來存取受保護資源 

**C** . 用戶端要認證自己並出示 Authorization Grant 來向授權伺服器換取 Access Token

**D** . 授權伺服器認證用戶端並驗證 Authorization Grant，
. . . 如果都合法，就核發 Access Token 

**E** . 用戶端出示 Access Token 向資源伺服器請求 Protected Resource

**F** . 資源伺服器驗證 Access Token ，如果合法就處理該請求

#### Refresh Token
* 如現有的 Access Token 過期而無效或是權限不足，需要再次取得 Token 時，就可以拿取 Refresh Token 向授權伺服器換新的 Access Token
* 不需要再次經過使用者的授權 
* 若授權伺服器選擇可核發 Refresh Token ，必須在核發 Access Token 時一併核發
* 新的 Access Token 時效和權限可能會比之前的少
* Refresh Token 不應該被提交到資源伺服器端

```
+--------+                                           +---------------+
|        |--(A)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(B)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(C)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(D)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(E)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(F)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(G)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(H)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+

        Figure 2: Refreshing an Expired Access Token
```

### 核發流程 Grant Type Flow
1. Authorization Code 
1. Implicit 
1. Password Credentials 
1. Client Credentials 

### (補充)HTTP 認證出示 token 的三種方式
1. 放在 Header 裡
```
Authorization: <type> <credentials>
```
![](https://ithelp.ithome.com.tw/upload/images/20180114/20107247ankhTWE8bF.png)

2. 放在 Request Body 裡
用表單POST
![](https://ithelp.ithome.com.tw/upload/images/20180114/20107247c35pHcinNq.png)

3. 放在 URL 裡
ex. 中央氣象局api

### Bearer Token
#### 解釋
一種協定（[RFC 6750](https://tools.ietf.org/html/rfc6750)）用來搭配OAuth2.0傳輸，示範了一種向資源端傳輸 Access Token 的方法
#### 用法
```php
Authorization: Bearer + base64(code) //in header
```

### OAuth vs. OpenID Connect
兩者的機制大致相同
* OAuth 的目的是**授權**（Authorization）
* OIDC 目的是**認證**（Authentication）

## JWT
是一種符合 Stateless 之產生token的方法，可**以 Bearer 做傳送**
用於認證(如類似Session使用者認證)、授權以及資料交換

### 結構
分為三個部分 `header` / `payload` / `signature`
#### header
* JSON 格式
* 定義 Token 種類
* 定義其雜湊演算法
```php
{
    “alg” :  “HS256”   //對稱式加密
    “typ” :  “JWT” 
}

```

#### payload
* JSON 格式
* 放置所要傳達的資訊
* 放置 registered claims
    * iss：發行方
    * aud：預期接收者
    * sub：聲明用於特定應用程序
    * iat：發行時間
    * exp：到期時間（以UNIX時間格式載）

```
{   
    “id” :  “1”
    “name” :  “Esther”  

    “exp” :  1601979022   
}

```
切勿放置隱私資訊於其中，因base64編碼能夠被輕易地轉換出來

#### signature
* 經由 Header 中所載之演算法處理
```php
HMACSHA256（
    base64Encode(header) + "." +
    base64Encode(payload),
    "256-bit-secret key"    //可先base64處理
）
```

### 組成
以 "." 分割成三個部分的字串 
![](https://i.imgur.com/kuv8foy.png)
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpZCI6IjEiLCJuYW1lIjoiRXN0aGVyIiwiaXNzIjoidGVzdC5teXNlbGYiLCJleHAiOjE2MDE5NzkwMjJ9.
Xv6AoLX-36GJv_hSobM8_iOCxQxfFTmZFmXGLnYxbRY
```
分別代表 base64(header + payload) + signature

:::info
除非知道密鑰值，否則若直接修改payload內容，會在與signature驗證時因不一致被擋下來。
:::


### JWS (簽章) vs. JWE (加密)
若使用非對稱式加密
隨著公私鑰持有方的不同，數據的流動方向和方式就分為了兩種
![](https://i.imgur.com/v68jLOn.png)
[參考資料](https://5xruby.tw/posts/what-is-jwt/)

### 使用者驗證的比較
#### JWT 驗證
![](https://miro.medium.com/max/700/1*kYXdr-UDLsWm5KCifi3jew.png)

* 優點：伺服器不需花費Session成本
* 缺點：失去對使用者的掌控權，無法隨時註銷某用戶直到其token過期

#### Cookie-based session 驗證
![](https://miro.medium.com/max/700/1*UjnxP7C6xVyqQ_PAXkxJEw.png)

* 優點：資料方便統一管理
* 缺點：Cookie 易被竄改、資料庫成本隨著用戶增加提高，每次驗證需經資料庫查詢耗費效能

### OWASP Top10
我懶得整理了ＸＤＤ

### 參考資料
[1] [OWASP Top 10 Security Risks & Vulnerabilities](https://sucuri.net/guides/owasp-top-10-security-vulnerabilities-2020/)
[2] [開發者必備知識 - HTTP認證（HTTP Authentication）](https://carsonwah.github.io/http-authentication.html)