簡介 Hydra

一直想來寫與 auth 相關的文章,過去在鐵人賽曾寫過,但當時在時間壓力下,其實沒有寫很好。今天就來輕鬆起個頭寫 auth 相關的文章吧!

11/22 更新 Hydra 的缺點。


Auth 相關的服務,最常會談到身分驗證(authentication)與授權(authorization)兩種行為,這兩種行為是不一樣的。身分驗證主要的目的是要知道「你是誰?」,授權則是要知道「你能讓我做什麼?」。

如果想要建置一個完整的 Auth 服務,現在已知的技術已經非常完整,基本該做的事情網路上都查得到。因此在基礎知識具備的前提下,從頭開始建置登入系統是非常自由沒有包袱的。

Hydra 的優勢剛好相反,它可以輕易地在既有系統上架構起現代化的 Auth 服務。

Hydra 可以做到什麼?

Hydra 實作了目前主流的 OAuth 2.0 協定,和建構在此之上的 OpenID Connect 協定。像 GitHub Authorizing OAuth Apps 是走 OAuth 2.0 的協定;而 LINE LoginSign in with Apple 則是走 OpenID Connect 協定。

簡單來說,如果想要建一個讓其他單位串接的中央身分驗證授權中心,Hydra 可以做到完全一樣的任務。不僅如此,而且還非常簡單。

Hydra 如何做到簡單導入?

Hydra 把整個登入流程分做兩個階段:Login 與 Consent,剛好對應到文章一開始提到的「身分驗證」與「授權」兩個行為。

Hydra 在啟動登入流程時,會產生一個 Login Challenge,它會被用來做為辨識未驗證使用者的唯一碼。而登入流程開始的第一步,會轉導去自定義的 Login Provider,這裡主要目的是要想辦法驗證使用者是誰,比方說帳號密碼,驗證完成要對 Login Challenge 標記完成驗證。接著會換自定義的 Consent Provider 處理授權相關的任務,與 Login 的流程大同小異。最後登出(Logout)也是差不多,先產生 challenge 再去自定義 provider 處理。

這整個流程裡,自定義 provider 可以處理各自的商業邏輯,比方說 Login Provider 可以在使用者沒有帳號的時候引導註冊新的。而完成流程只要對 challenge 標記,並把導頁流程交由 Hydra 控制即可。

實務上,在舊的登入系統裡,Login Provider 是可以直接使用原有的登入頁改寫--差異只在一開始進入登入頁只會有 login challenge,以及離開登入頁需要照 Hydra 流程進行。

是的,就是進入登入頁和離開登入頁這兩個關鍵點。只要了解並掌握這點,就能很輕鬆的把 Hydra 導入既有系統。

Hydra 的缺點

評估技術一定要看缺點,它總會在很特別的時機點咬你一口。

Hydra 被設計成容易導入到各個既有系統中,在實作導入過程是非常開心的,但它有個致命的缺點--過多的轉導過程,造成網頁回應緩慢,影響使用者體驗。舉個例:一般網站在遇到需要做身分驗證的時候,只需要導頁至登入頁,打完帳密驗證完再轉導至對應頁面即可。把這段流程用甘特圖表現如下:

gantt
dateFormat -
axisFormat -
轉導登入頁: p0, , 1s
登入頁: active, p1, after p0, 1s
身分驗證完成轉導: p2, after p1, 1s
目標頁: active, p3, after p2, 1s

Hydra 呢,非常可怕。

Hydra 的設計是流程由 Hydra 啟動、控制與結束,所以有很多步驟需要再轉導到 Hydra,進而產生龐大的轉導開銷。一樣的例子,遇到需要做身分驗證時,第一步是轉導到 Hydra,從這步開始畫甘特圖:

gantt
dateFormat -
axisFormat -
最一開始轉導 Hydra: p0, , 1s
轉導 Login Provider(登入頁): p1, after p0, 1s
登入頁: active, p2, after p1, 1s
身分驗證完成轉導 Hydra: p3, after p2, 1s
轉導 Consent Provider(授權頁): p4, after p3, 1s
授權頁: active, p5, after p4, 1s
授權完成轉導 Hydra: p6, after p5, 1s
Hydra 轉導 redirect_uri: p7, after p6, 1s
client 轉導目標頁: p8, after p7, 1s
目標頁: active, p9, after p8, 1s

如果所有使用者都有經過登入頁與授權頁的流程,其實問題並不大,最大的問題在於這兩個流程被省略的情境:把 OpenID Connect 作為單點登入(SSO)的解決方案,且剛好又沒有必要的授權流程時,瀏覽器就得吃下 7 個轉導(不含登入頁與授權頁)才能進目標頁。筆電和桌電連線的速度比較快,一個轉導可能 50ms ~ 100ms 就搞定了,7 個轉導不到 1 秒就解決了;最怕的是極不穩定的行動網路,嚴重可能要到 300ms ~ 500ms,7 個轉導就要 3.5 秒,使用者早就跳出了。

即使 Hydra 是使用高效能高並發的 Golang 語言撰寫,仍然無法有效減少轉導過程拖延的時間,這是選擇 Hydra 要考慮的最重要問題。

其次則是如何在跨站存取的同時保存 session。Hydra 本身即可建置一個 domain 與服務,而登入頁和授權頁可能會是不同的服務,還有 Client 端也是一個服務,如何在這四個服務間共享 session 將是需要特別設計的。

Client 與 Hydra 的 session 是使用 Hydra 本身設計 session 機制建置的,而登入頁和授權頁共享資料的方法,Hydra 也有特別設計,這兩個機制未來有機會再說明。

參考資料