深入淺出 OpenID Connect (一)
一個基於 OAuth2.0 發展而成的認證機制
前言
這陣子由於想要針對 API security 中的認證領域做深入研究,因此接觸到了OpenID Connect (以下稱之為 OIDC ) 這個協議。而關於 OIDC 的實際應用大家應該也很熟悉,像是網站或App登入時,常常用到的「以 Facebook、Google、Line 帳號登入」的功能,也就是透過第三方組織提供相關使用者資訊,以協助網站或 App 能夠識別使用者身分,藉以提供使用者客製化的服務。
目前不管是商業領域或是學術領域都有不少基於 OIDC 的相關延伸應用,因此是一個很不錯的切入點。這個系列文將分成兩篇,第一篇將會概略介紹 OIDC 及其起源,也會從 OIDC 的基礎:OAuth2.0 協議切入討論。第二篇將會介紹 OIDC 官方文件中所提供的三種認證流程,包含介紹不同流程所適用的系統及其相關特性。
最後,本系列文將主要參考 OIDC 官方文件,OAuth2 in Action 所提供的資料做整理,也會以一些網路上的資料做參考補充。
如何在 OAuth2 上建立一個認證機制
想到第三方認證,一般做軟體工程的人第一個常常想到 OAuth2,但其實這個想法並非完全正確,主要原因是 OAuth2 並不是一個認證 (Authentication)機制,而只是一個單純的授權 (Authorization)機制,也就是正如其名:Open Authorization。
為什麼OAuth2並不是認證機制?
一般來說,認證的工作最重要的是協助軟體系統驗證「是否使用者存在?」與「使用者是誰?」,但在 OAuth2 中,客戶端 (Client)僅憑授權伺服器所提供的 Access token 來取得受保護的資源 (Protect Resource),在整個授權的流程中,客戶端並無法得到任何使用者的相關資訊。因此,我們並不能稱 OAuth2 為認證機制。
巧克力 (chocolate)與乳脂軟糖 (fudge)
在 <OAuth2 in Action> 書中,舉了一個很不錯的例子來說明「授權」與「認證」兩種協議的差別。
“巧克力可以用來製作成軟糖,也可以用來製成很多不同的產品;軟糖能以巧克力做成巧克力軟糖,但是也可以透過別種原料做成橘子軟糖等等…”
而 OAuth2 代表的就是巧克力,是很多授權機制的基礎,也可以用來製造身分 (make an identity)或是認證API;
認證協議則是一種軟糖,需要結合一些關鍵的加密、識別元件 (例如:生物特徵、帳號密碼)或是流程,才能使認證系統變得更適合與安全。
如何將 OAuth2 中的角色對應 (mapping)到認證協定?
依照上面的論述,OAuth2 可作爲建構認證協定的一種流程。但在實務上要如何結合兩個不同命題 (授權與認證)的協定會是一個需要思考的問題。在認證的過程中,使用者 (End-user) 需要使用的服務端,稱之爲 Relying Party (以下簡稱爲RP),RP 需要識別 End-user 的資訊來提供其客制化的服務;另一方面 Identity Provider (以下稱之爲IdP)負責提供被保護的使用者資料。
第一種對應的想法 (如下圖),由於 End-user 需要請求 RP 的服務授權,故將 RP 視爲一種被保護的資源,即將 OAuth2 中 Protected Resource 的角色對應到 RP,而由於 IdP 主要負責提供登入 RP 用的相關資訊,所以將 IdP 對應到 OAuth2 中的 Authorization Server。然而,這樣的對應將會遇到跨界安全 (Security domain boundary crossed)的問題。即在 OAuth2 中直接由 End-user 與 Protected Resource 互動,造成安全性的風險 (詳細可以參考 <OAuth2 in Action> 中内容)。因此,這種對應方法是不可行的。
第二種對應的想法 (如下圖),直接將 RP 視爲 OAuth2 中的 Client 角色,透過 IdP (即 Authorization Server)的授權取得 IdP 中所提供的使用者被保護資訊,以利使用者登入 RP。如此一來,認證系統就能直接透過 OAuth2 所提供的授權協議流程,來建構使用者即時授權認證的方法。
以 OAuth2 爲基礎建構認證協議的優劣勢
而在授權機制上建構認證機制,最大優勢就是 End-user 可以做到被保護認證資料提供的即時授權。下面也分別列出以 OAuth2 授權機制建構認證機制的優勢與設計挑戰。
優勢
- 彈性:使用者可以選擇提供想要的資訊給應用程式 (RP)
- 兼容性:若某項服務已經在使用 OAuth2 協議,那再提供基於 OAuth2 的驗證服務也就不費吹灰之力
- 可追蹤性:User 知道他自己把身分提供給誰,IdP 也可以決定哪些 client可以取得身分資訊
設計挑戰
- 將 Access token 當作認證資訊 (proof of authentication):Access token 在OAuth2 中僅是一種授權的象徵,不具任何可利用的資訊。
- 將能夠存取 Protected API 作為認證的象徵:因為在 OAuth2 中,有時不需要取得 End-user 的即時授權就能夠獲得 Access token ,但是認證系統一個很重要的需求就是能夠隨時確保 End-user 是否存在。
- Access token 的注入 (Injection)攻擊:OAuth2 中一種很常見的攻擊,就是攻擊者透過調包 Access token,來使得 Client 訪問無關的資源。但是在認證場景中,這會導致災難性的問題。
- 無法辨識 Access token 的發送目的:在 OAuth2 的官方規格裡,授權請求的過程,Client 並無法確認是否 Access token 所傳送的對象真的是自己。
- 注入假使用者資訊:攻擊者可能會在OAuth2 授權請求過程竄改傳送給Client 的資訊,因此,在傳輸過程,需要透過加密 (如:TLS)來傳輸。
- 沒有統一的標準:就算不同認證系統皆基於 OAuth2 協議建構,也有可能產生大不同的結果。因此,一套業界同意的標準會是必要的。
初探 OpenID Connect
上面完整的介紹了在 OAuth2 上建置認證協議的可行性與相關挑戰。OIDC 正是為了解決上述問題而設計出來的一套基於 OAuth2 的即時認證協議。而協議中元件的概覽如下圖。OIDC 除了其核心協議之外,也定義了 IdP 的服務發現與動態 Client 註冊等協議;另一方面,OIDC 一部分的token也是利用 JSON Web Tokens (JWT)系列的token來實作。
OIDC 角色介紹
在介紹角色與元件之前,先提供一個應用案例:首先,Alice 要使用一個購票A網站的服務,而他並不想註冊會員,而是選擇透過第三方 (例如:臉書)的方式登入。經過整個登入流程後,Alice 成功登入 A 網站,而 A 網站則取得 Alice 的姓名,信箱,大頭貼等資訊。之後 A 網站能將購票資訊寄至 Alice 的信箱。
在本文前段有提到將 OAuth2 mapping 到認證系統後的角色。而 OIDC 部份也大致一致,End-user (案例中的 Alice)是主要的服務使用者;RP (案例中的 A 網站) 需要識別 End-user 的資訊來提供其客制化的服務;IdP (案例中的臉書)為負責相關認證資料提供的授權機制; Identity Profile API (案例中的提供認證資訊的 API) 則提供與儲存被保護的 End-user 相關資訊。
OIDC token介紹
OIDC 除了沿用 OAuth2 中的 Access token 來作為認證資訊的授權憑證,另一方面,為了解決上述的設計挑戰,也導入了名為 ID token的 secondary token。ID token 主要攜帶相關的驗證資訊 (為解決上述的設計挑戰,例如:提供 hash 值以確保 access token 與 authorization code 的完整性。)與存取 Identity Profile API 的相關資訊,並透過 JOSE 的方式將明文以加密的方法傳送,確保認證資訊的機密性與不可否認性。ID token 所包含的內容 (claims)如下,詳細可參考 OIDC 官方文獻。
iss:發布者的URL
sub:subject identifier。通常用來代表特定End-user的識別碼
aud:token逾傳送的對象。通常會是client ID的形式
exp:id token 到期時間
iat:發布 (issue)的時間
nonce:用來防止replay attack。回傳RP在發出認證請求 (authentication request)時,所攜帶的隨機數 (如果RP有傳送它的話就應該被回傳)
c_hash:authorization code的雜湊值。用來驗證其完整性
at_hash:access token的雜湊值。用來驗證其完整性
ID token 範例
{
"iss": "https://server.example.com",
"sub": "24400320",
"aud": "s6BhdRkqt3",
"nonce": "n-0S6_WzA2Mj",
"exp": 1311281970,
"iat": 1311280970,
"auth_time": 1311280969,
"acr": "urn:mace:incommon:iap:silver"
}
ID token 的相關驗證手段
ID token 是用來提供 RP 初步的認證資訊,協助解決在執行認證流程時可能遇到的挑戰。以下列出了 ID token 的相關驗證手段與方法。
- 解析 JOSE 並收集其提供的相關的 claim
- 驗證 ID token 確實被 IdP 的公鑰簽名
- 確認 ID token 確實是被可信任的 IdP 所核發
- 透過 audience 欄位 (帶有 client identifier)確認 ID token 確實要發送給 RP
- 驗證 expiration, issued-at 的時間小於目前的timestamp
- 確認 ID token 中所帶的隨機數 (nonce),與 authentication request 中所帶有的一致
- 透過 ID token 中提供的 c_hash 與 at_hash 驗證 authorization code 或access token 沒有被竄改
結語
在 OIDC 系列文 (一),主要從 OAuth2 授權機制的角度切入,介紹了 OIDC 協議的基礎,及其背景知識。對於想要針對 OIDC 研究的讀者來說,了解其來龍去脈是很重要的事;另外,本文也初探了 OIDC 的概括及其相關角色與元件,而下篇 (系列文二) 將介紹 OIDC 官方規格中提供的三種認證流程,並分析各個流程的使用場景與優劣勢。
參考文獻
[1] OAuth2 in Action
[2] Sakimura, N., Bradley, J., Jones, M., De Medeiros, B., & Mortimore, C. (2014). Openid connect core 1.0. The OpenID Foundation, S3.