2023/09/18

OAuth

傳統的 Client-Server 架構裡, Client 要拿取受保護的資源 (Protected Resoruce) 的時候,要向 Server 出示使用者 (Resource Owner) 的帳號密碼才行。如果要讓第三方應用程式也可以使用這些 Resources ,則需要 Resource Owner 把帳號密碼給這個第三方應用程式,這時候會產生以下的問題:

  • 第三方應用程式必須以明碼儲存 Resource Owner 的帳號密碼
  • Server 要支援密碼認證
  • 第三方應用程式會得到完整存取 Protected Resources 的權限,無法限制時效
  • Resource Owner 無法只撤回某一個第三方應用程式的存取權,必須要修改密碼才能撤回。
  • 當某一個第三方應用程式被破解,就會導致使用該密碼的所有資料被破解。

OAuth 解決這些問題的方式,是引入一個認證層 (authorization layer) ,並把 client 跟 resource owner 的角色分開。Client 會先索取存取權,來存取 Resource Owner 擁有的資源,這些資源會放在 Resource Server 上面,並且 Client 會得到一組不同於 Resource Owner 所持有的認證碼,也就是 access token。

角色定義

  • Resource Owner

    可授權別人去存取 Protected Resource。如果這個角色是人類的話,就是指使用者 (end-user)。

  • Resource Server

    存放 Protected Resource 的伺服器,可以根據 Access Token 來接受使用 Protected Resource 的請求。

  • Client

    讓 Resource Owner 授權後,可以去存取 Protected Resource 的應用程式。

  • Authorization Server

    認證 Resource Owner 並獲得 Resource Owner 許可後,核發 Access Token 的伺服器。

+--------+                               +---------------+
|        |--(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 ---|               |
+--------+                               +---------------+

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        +---------------+

Grant Flow

Authorization Code Grant Type Flow

+----------+
| Resource |
|   Owner  |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier      +---------------+
|         -+----(A)-- & Redirection URI ---->|               |
|  User-   |                                 | Authorization |
|  Agent  -+----(B)-- User authenticates --->|     Server    |
|          |                                 |               |
|         -+----(C)-- Authorization Code ---<|               |
+-|----|---+                                 +---------------+
  |    |                                         ^      v
 (A)  (C)                                        |      |
  |    |                                         |      |
  ^    v                                         |      |
+---------+                                      |      |
|         |>---(D)-- Authorization Code ---------'      |
|  Client |          & Redirection URI                  |
|         |                                             |
|         |<---(E)----- Access Token -------------------'
+---------+       (w/ Optional Refresh Token)
  • 要向 Authorization Server 先取得 Grant Code 再取得 Access Token。
  • 適合 Confidential Clients ,如部署在 Server 上面的應用程式。
  • 可以核發 Refresh Token。
  • 需要 User-Agent Redirection。

Implicit Grant Type Flow

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier     +---------------+
|         -+----(A)-- & Redirection URI --->|               |
|  User-   |                                | Authorization |
|  Agent  -|----(B)-- User authenticates -->|     Server    |
|          |                                |               |
|          |<---(C)--- Redirection URI ----<|               |
|          |          with Access Token     +---------------+
|          |            in Fragment
|          |                                +---------------+
|          |----(D)--- Redirection URI ---->|   Web-Hosted  |
|          |          without Fragment      |     Client    |
|          |                                |    Resource   |
|     (F)  |<---(E)------- Script ---------<|               |
|          |                                +---------------+
+-|--------+
  |    |
 (A)  (G) Access Token
  |    |
  ^    v
+---------+
|         |
|  Client |
|         |
+---------+
  • Authorization Server 直接向 Client 核發 Access Token (一步)。
  • 適合非常特定的 Public Clients ,例如跑在 Browser 裡面的應用程式。
  • Authorization Server 不必(也無法)驗證 Client 的身份。
  • 禁止核發 Refresh Token。
  • 需要 User-Agent Redirection。
  • 有資料外洩風險。

Resource Owner Password Credentials Grant Type Flow

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     v
     |    Resource Owner
    (A) Password Credentials
     |
     v
+---------+                                  +---------------+
|         |>--(B)---- Resource Owner ------->|               |
|         |         Password Credentials     | Authorization |
| Client  |                                  |     Server    |
|         |<--(C)---- Access Token ---------<|               |
|         |    (w/ Optional Refresh Token)   |               |
+---------+                                  +---------------+
  • Resource Owner 的帳號密碼直接拿來當做 Grant。
  • 適用於 Resource Owner 高度信賴的 Client (像是 OS 內建的)或是官方應用程式。
  • 其他流程不適用時才能用。
  • 可以核發 Refresh Token。
  • 沒有 User-Agent Redirection。

Client Credentials Grant Type Flow

+---------+                                  +---------------+
|         |                                  |               |
|         |>--(A)- Client Authentication --->| Authorization |
| Client  |                                  |     Server    |
|         |<--(B)---- Access Token ---------<|               |
|         |                                  |               |
+---------+                                  +---------------+
  • Client 的帳號與密碼直接用來 Grant
  • 適用於跑在 Server 上面的 Confidential Client
  • 不建議核發 Refresh Token
  • 沒有 User-Agent Redirection

References

OAuth 2.0 筆記 (1) 世界觀

OAuth 2.0 筆記 (4.1) Authorization Code Grant Flow 細節

OAuth 2.0 筆記 (4.2) Implicit Grant Flow 細節

OAuth 2.0 筆記 (4.3) Resource Owner Password Credentials Grant Flow 細節

OAuth 2.0 筆記 (4.4) Client Credentials Grant Flow 細節

各大網站 OAuth 2.0 實作差異 2013

沒有留言:

張貼留言