OAuth 2.0 筆記 (2) Client 的註冊與認證

在 OAuth 2.0 的 spec 裡面,關於註冊 Client (Registration) 這件事,只定義了抽象的概念、類型 (profiles) 與要求,以及基於保密能力把 Clients 分成兩類: confidentialpublic

而認證 (Authentication) 的流程則是有規定需要傳送的資料。所謂的認證,就是 Client 要向 Authorization Server 證明自己的身份,若把 Client 比喻為人類使用者的話,就像是打帳號密碼之類的動作。在 spec 內建的流程中,需要認證 Client 的地方只有 Token Endpoint,就是「發給你 Token 的時候」認證。其中 Implicit Flow 並沒有認證 Client (也沒有經過 Token Endpoint)。

Client 的註冊

Spec 不規定 Client 如何向 Authorization Server 註冊自己,通常是用 HTML 界面。註冊時, Authorization Server 與 Client 之間不需要有直接互動,如果 Authorization Server 支援的話,註冊的過程可以依賴其他的手段來建立互相的信任、取得 Client 的註冊資料(Redirection URI 、Client Type 等)。例如,可以透過內部的通道來搜尋 Client 。

註冊的時候, Client 的開發人員應該要做這些事:

Section 2

Client Types

在 spec 裡面,根據有沒有能力保密 client 的 credentials (帳號密碼),定義了兩種 Client Types:

confidential:Client 可以自我保密 client 的 credentials(例如跑在 Server 上面,且可以限制 credentials 的存取),或是可以用別的手段來確保認證過程的安全性。

public:Client 無法保密 credentials (Native App 或是跑在 Browser 裡面的 App),或是無法用任何手段來保護 client 的認證。

Authorization Server 不應該自行猜測 Client 屬於何種。(不過現實卻不是這樣,見下文。)

單一的 Client 可能會分離成不同的組件 (components) ,如一個跑在 Server 、一個跑在 Client 。若 Authorization Server 沒有支援這種 Client ,或沒有指南文件,則開發人員時必須為各個組件註冊不同的 Clients。

Section 2.1

Client Profiles

OAuth 2.0 的 spec 是為以下這些類型的 Clients 來設計的:

Web Application

User-Agent-based Application

Native Application

舉例:

應用程式 Profile Type
自動抓 Facebook 照片的某個伺服器程式 Web Application Confidential
可以連結 Facebook 帳號的 Firefox Add-On UA-based Application Public
iPhone 版的 Facebook 即時通訊程式 Native App Public

出自 Section 2.1,範例除外

現實中的 Client Registration

雖然規定註冊時要填寫 Client Type ,實務上好像沒什麼網站會要求填寫 Client Type 的,甚至 Client Profile,在整份 API 裡面,即使會區分 client ,也是把 client 依其 Profiles 區分。

Client Identifier (識別號)

Client 的惟一識別號,註冊時取得,對 Authorization Server 也是惟一的。

會被 Resource Owner 看到,所以絕對不可以在 Client Authentication 的時候單獨使用。

其長度 spec 並不規定。Client 不可自己猜測。Authorization Server 應該要在文件裡提及。

Section 2.2

認證 Client 的方式 (Authentication)

confidential:要有認證流程,其流程要符合 Authorization Server 的安全規範。通常是用事先核發的 credentials (如 Password 、非對稱式金鑰)。

public:可以有認證方式(不必備),但絕對不能以 Public Client 的認證方式來識別 (identify) 個別的 client 。

Client 每一次 request 只能用一種方式來認證。

Section 2.3

用 Client Password 來認證

方法 (1): HTTP Basic Auth

持有 Password 的 Client 可以用 HTTP Basic Auth 來認證(見 RFC 2617)。帳密要先用 urlencode 編過。

例如 ID 是 s6BhdRkqt3 、 Secret 是 7Fjfp0ZBr1KtDRbnfVdmIw ,則步驟如下:

Step 1: 根據 Basic Auth 的規則,把 ID 和 Secret 連起來,中間用冒號 : 分開,變成這樣:

s6BhdRkqt3:7Fjfp0ZBr1KtDRbnfVdmIw

Step 2: 用 base64 編過,變成這樣:

czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

Step 3: 加上 Basic 前綴:

Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

Step 4: 最後得到的 HTTP Auth 的 header 就是:

Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

方法 (2): POST

此外還有另一種方法(不建議使用)是使用 POST 發送以下資料:

參數名 必/選
client_id
client_secret 若本來就是空白的密碼,則可留空。

注意事項:

範例:(換發 Access Token 時,Client 要認證自己)

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

Section 2.3.1

其他認證方式

沒規定不能有別的,只要 Authorization Server 沒有安全上的疑慮就好了。

不過,如果要做別的認證方式,必須要建一張表記錄認證方式跟 Client ID 。

實際上的利用方式

理想與現實總是有段差距。實務上,許多大網站只支援 POST ,Basic Auth 則不一定支援。而 Facebook 則是只支援 GET (不符合「不可以放在 URI 裡面」的要求)。

未註冊的 Clients

沒規定不能有這種 Client 存在,spec 裡面也不討論。

關於 Native Application

Native Application 指的是在 Resource Owner 的設備上面安裝、執行的 Client (即桌面應用程式、手機 App),需要特別考慮安全性、平台相容性、整體的 User Experience 。

Authorzation Endpoint 會要求 Client 和 Resource Owner 的 User-Agent 之間的互動。Native Application 可以調用外部的 User-Agent 或是內嵌一個在應用程式裡面。用法如下。

外部 User-Agent:

內嵌 User-Agent:

外部或內嵌 User-Agent 的選擇

在選擇要用哪一種 User-Agent 的時候,請考慮以下這些事:

Grant Flow 的選擇

Native Application 可以用的流程是 Implicit Grant 和 Authorization Code Grant 。在選擇要用哪一種的時候,請考慮以下這些事:

Section 9

安全性問題

這裡的安全性問題出自 Section 10 ,因為跟 Client Authentcation 有關,所以直接放進來。

Client 認證的安全性問題 (Section 10.1)

Authorization Server 設立 Client credentials 是為了認證 Client。建議 Authorization Server 考慮使用比 Client password 更強的認證方式。Web Application Clients 必須確保 Client password 和其他 credentaisl 的保密。

Authorization Server 不可以為了認證 Client 而核發 Client Passwords 或是其他 credentials 給 Native Application 或是 User-Agent-Based Application Clients ,但是可以核發給特定設備上面的 Native Applciation 。

如果 Client 認證無法實施,Authorization Server 應該使用別的方式來驗證 Client 的身份。例如,要求 Client 預先設定 Redirection URI,或是讓 Resource Owner 來確認 Client 的身份。雖然,在詢問 Resource Owner 的授權的時候,即使有正確的 Redirection URI ,也不足以驗證 Client 的身份, 但是可以防止 credentails 傳遞到假的 Client 。

對於未經認證的 Clients (如 Public Clients),Authorization Server 必須考慮與其互動時會引發的安全性衝擊,且核發給這種 Clients 的其他 credentials 有外洩的可能(例如 Refresh Token),應致力降低其可能性。

偽裝成別的 Client (Section 10.2)

Client 可能會被駭,像是 credentials 外洩。這種情況發生時,惡意的 Client 可以偽裝成被駭的 Client 並取得存取 Protected Resource 的權限。

Authorization Server 必須儘可能認證 Client 。如果 Authorization Server 因為 Client 的性質而不能認證之(例如 In-Browser App 就不能認證),那麼 Authorization Server 必須要求其預先設定 Redirection URI 來接收授權的 response,並且應該利用其他手段來保護 Resource Owner 使用這種潛在的惡意 Client 。

Authorizatino Server 應該要強化明確的 Resource Owner 授權流程,並且提供 Resource Owner 關於 Client 要求的授權範圍 (scope) 以及時效。Resource Owner 在當下的 Client 的環境裡面,要不要檢閱這些資訊、要不要授權或拒絕請求,則是他的自由。

當 Authorization Server 收到重複的授權請求的時候,要是 Resource Owner 本人沒有與 Authorization Server 互動、Client 沒有認證自己、又沒有其他方法可以確定重複的請求是來自真正的 Client 而不是偽裝的,則 Authorization Server 不應該處理重複的授權請求。

Open Redirector

沒要求 Client 事先指定 Redirection URI ,可能會使得 Authorization Endpoint 變成 Open Redirector 。詳見系列文第 3 篇關於 Open Redirector 的安全性問題。


OAuth 2.0 系列文目錄