geoffreylitt.com 最近在 dead-Twitter 上提出了一個關於 OAuth 的問題:

有許多關於 OAuth 內部機械運作的解釋,也有很多關於各種流程如何運作的解釋,但 Geoffrey 提出的問題卻是不同的:

在我撰寫 OAuth 規格初稿的 19 年後(!),雖然增加了許多細節和雜訊,但核心概念始終如一。幸運的是,這個核心非常簡單。Geoffrey 是個非常聰明的人,他提出這個問題讓我覺得是時候寫下答案了。

或許從「登入」這個使用案例開始會比較容易,這是一個比核心 OAuth 更複雜的規格(OpenID Connect)。OIDC 在底層使用了 OAuth,但有助於我們理解實際發生情況的核心。

OIDC 在功能上等同於「魔法連結」驗證。

我們將一個秘密傳送給一個只有試圖驗證身分的人才能存取的地方,然後他們透過向我們展示這個秘密來證明他們能夠存取該地方。

其餘的只是累積的共識,部分是為了協調(例如同意詞彙等),部分是使用者體驗,部分是確保所有特定機制都是安全的。

從 OIDC 開始解釋這一切如何運作也有歷史原因:在 2006 年底,我當時在 Twitter 工作,我們希望支援 OpenID(當時是 1.0 版),以便 ahem Twitter 不會成為線上身分識別的中心持有者。與 OpenID 的人聊過之後,我們很快意識到,按照當時的架構,我們將無法同時支援桌面用戶端和網頁登入,因為我們的用戶將不再需要密碼!(當時行動應用程式還不存在,但也不遠了)。所以,為了支援 OpenID 登入,我們需要一種方式讓透過第三方用戶端使用 Twitter 的人能夠在沒有密碼的情況下登入。

對此有很多解決方案;Flickr 有一種方法,AWS 有一種,delicious 有一種,許多網站只是讓隨機的其他應用程式使用你的密碼登入你的帳戶,等等,但「Web 2.0」時代的幾乎所有網站都需要一種方法來做到這一點。它們都不安全,而且都是完全客製化的。

與其建立 TwitterAuth,我認為是時候制定一個標準了。請參考 XKCD 927:

幸運的是,儘管困難重重,我們現在有一個委託授權的標準。它的作用非常簡單:

核心來說,OAuth 用於委託授權,是一種標準化的方法來執行以下操作:

第一部分是將一個可重複使用的秘密,在使用者同意的情況下,傳送給一個已知的代理。

OAuth 的另一半詳細說明了代理如何使用該秘密,代表最初同意的使用者進行後續請求。

就是這樣。其餘的(可悲的是,大多是必要的)雜訊。

顯然,上述內容省略了關於如何安全且以一致的可互操作方式完成這些細節的龐大資訊。這是標準制定機構無可避免的工作。我對我們目前的標準制定機構的優缺點有很多看法,但那又是另一回事了。

有非常可信的論點認為,描述 OAuth 的 IETF 標準集與其說是一個標準,不如說是一個框架。我認為這也未嘗是壞事。HTML 也是一個框架——根據設計,並非所有瀏覽器都需要實施所有功能。

OIDC 本身很有趣——在創建 OAuth 後不久,我們就意識到可以透過 OAuth 來組合 OpenID 的行為,儘管當時不可能使用 OpenID 來做 OAuth 所做的事情。由於各種社會、政治、技術和營運原因,花了將近十年的時間才將這些想法寫下來並在世界上實現。我認為 OAuth 的一項重大成功是,我完全沒有參與這項工作。我沒有孩子,但我知道創造出一個能獨立發展的事物時,那種非凡而複雜的感受。

更廣泛地說,身分驗證和授權是複雜且情境化的問題,無法與整合它們的系統的使用者體驗和架構考量分開。

實施像 OAuth 這樣的標準時,最重要的是首先了解你試圖做什麼以及為什麼。一旦確定了這一點,如何做通常是一個「簡單」的機械問題,要求相對受限。我認為這就是為什麼 Geoffrey 的問題如此有力的原因——它深入探討了 OAuth 對許多人來說常常難以理解的核心:標準的複雜機制意味著它所編碼的實際目標被忽略了。

希望這篇文章能有所幫助!