# 從 RFC 規格書觀點解析 OAuth 2.0

**co-author:** [**MowLi 微風**](https://medium.com/u/e56c5b49cd7e)

**OAuth2規格書中，對資源也自定義的分配，下表為rfc中所分配的角色分配表:**

| 角色                   | 說明                                           |
| -------------------- | -------------------------------------------- |
| Client               | 所使用的存取工具或程式，如 Browser, Mobile Phone, Postman |
| Resource Owner       | 具備服務存取資格的人                                   |
| Authorization Server | 負責認證的伺服器，主要負責發行Access Token                  |
| Protected Resource   | 欲存取的服務                                       |

舉一個最常被 OAuth 相關書籍提及的例子：你(Resource Owner)有一張儲存在雲端服務的相片(Protected Resource)，今天你想要透過一個影印服務(Client)去列印該相片。

在傳統做法上，為了讓影印服務(Client)拿到相片就必須將你的雲端服務的憑證（例如：帳號密碼）給這個影印服務，讓它能存取該雲端服務的資源。而 IETF RFC 6749 及 Action 書中列出了一些缺點：

* Client 需要儲存資源所有者的憑證，通常會是明文形式的密碼
* Client 擁有過大對受保護資源的訪問權限，而且資源所有者沒有辦法限制它訪問時間或訪問資源的範圍
* 資源所有者只能透過更改雲端服務的密碼來撤銷影印服務的訪問權限，而且沒有辦法只撤銷一個（其它用到雲端服務的 Client 應用程式都會受到影響）
* 如果 Client 受到攻擊，該攻擊者還能存取受保護資源，以及資源擁有者其它使用相同密碼的服務（很多人在不同網站都設同一組帳密）

綜觀來說，在 OAuth2 中：

1. Client 必須先向 Resource Owner 請求授權來獲得 Authorization Grant，這裡面會包括 Client 能存取資源的範圍。
2. Client 藉由 Authorization Grant 向 Authorization Server 獲取一個有時效性/永久性的 Access Token。
3. 以 Access Token 來存取 Protected Resource，而不是直接以 Resource Owner 的帳號密碼來存取。

![OAuth2 Framework](https://cdn-images-1.medium.com/max/800/1*VyrcXzN1D0vpOw9Y5TIR9A.png)

簡單來說，Client若要存取服務的話，首先要先拿到**Authorization Grant**，再使用Grant拿取**Access Token**，最後再使用Access Token**存取服務**。

![Access Work Flow in OAuth2](https://cdn-images-1.medium.com/max/800/1*l5TgbUBqMWW0wvPn8-wdJw.png)

### Authorization Grant依照存取程度分為四種方式存取 Protected Resource:

* **Authorization Code**

  **屬於比較廣泛被使用的**，client 取得 Authorization Code 才能以此換取access token。

![Authorization Code Grant](https://cdn-images-1.medium.com/max/800/1*nJVTrVbGWxxjD0ZUulzo5A.png)

* **Implicit**

  是相對安全性來的稍微低一點，是直接取得 access token。好處是可以減少存取的 round trip 加速認證的過程。

![Implicit Grant](https://cdn-images-1.medium.com/max/800/1*cKtqMkJIsoUP_soge2bhiQ.png)

* **Resource Owner Password Credentials Grant**

  指的是直接透過 password 直接從 Authorization Server 取得 access token，比較適合使用在可以信任的 client。

![Resource Owner Password Credentials Grant](https://cdn-images-1.medium.com/max/800/1*Z2dTiCFcvJBpo_MooR1uAg.png)

* **Client Credentials**

  完全信任 client，直接取得 token 直接存取 Protected Resource。

![Client Credentials Grant](https://cdn-images-1.medium.com/max/800/1*etZk9o-phnwO4OhrPIxYEQ.png)

以 Authorization Server 角度而言，client 主要分為兩種 confidential 與 public，就字面上意義 confidential 屬於可以直接被信任的、public 屬於不被信任的存取者。不被信任的 client 取得 Grant 的方式建議為：Authorization Grant、Implicit 的方式 ; 若是屬於信任的 Client 建議為：Resource Owner Password Credentials Grant、Client Credentials。

![img](https://cdn-images-1.medium.com/max/800/1*cQXlaXecHX20SgikrFq8WQ.png)

> 1. public 指的是 Resource Owner 是屬於一般使用者而非內部開發者，因此在進行取得憑證的過程應該使用較高的安全性的方式。
> 2. confidential 指的是 Resource Owner 是屬於內部開發者的，因為服務間會互相調用，因為是可信任的服務，因此用的憑證相對的比外部得來的寬鬆。

### 總結

OAuth 2 並不是專屬給第三方程式存取認證模式，它本身是一種框架，適用任何的認證情況。事實上在 IETF RFC 文件中，針對不同的 client 有不同強度的認證方法。市面上主要廣泛運用在存取第三方程式通常都以 Authorization Grant 的方式進行存取。然而 OAuth 2 其實也可以運用在內部 Service 自己存取時的場景！

### **參考資料**

\[1] Hardt, Dick. RFC 6749: The OAuth 2.0 Authorization Framework. Internet Engineering Task Force (IETF) 10 (2012): 2070–1721.
