前言
最近在對基於token做身份認證的專案中擴充套件sso。
背景
專案大致架構如下
其中伺服器端是RESTful風格的API伺服器,客戶端基於Vue開發的SPA。
身份認證是基於token,客戶端登入之後,伺服器端驗證併傳送JWT token給客戶端,客戶端將token存入localStorage中並每次恢復到Vuex中,客戶端每次請求都會在HTTP自定義頭部中附帶token。
本文簡述下我對OIDC解決方案的簡單理解以及基於上述架構實現sso的思路。
正文
OIDC的官方解釋如下
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
也就是OAuth2.0只解決了資源的訪問和分享,OIDC則基於此實現了使用者的認證。它的主要目的是提供一次登入,多個站點享有登入狀態。也就是當使用者在某一使用OIDC的網站登入時,使用者被重定向到OpenID站點登入,然後重定向回原來網站。
OIDC已經有很多的企業在使用,比如Google的賬號認證授權體系,Microsoft的賬號體系也部署了OIDC,當然這些企業有的也是OIDC背後的推動者。
OAuth2提供了Access Token來解決授權第三方客戶端訪問受保護資源的問題;相似的,OIDC在這個基礎上提供了ID Token來解決第三方客戶端標識使用者身份認證的問題。OIDC的核心在於在OAuth2的授權流程中,一併提供使用者的身份認證資訊(ID-Token)給到第三方客戶端,ID-Token使用JWT格式來包裝,得益於JWT(JSON Web Token)的自包含性,緊湊性以及防篡改機制,使得ID-Token可以安全的傳遞給第三方客戶端程式並且容易被驗證。應用伺服器,在驗證ID-Token正確之後,使用Access-Token向介面換取使用者的更多的資訊。
OIDC到底怎麼執行的
第一期先從簡,也不討論什麼OIDC協議族,就單單說一下OIDC是怎麼運作的。以還是以午安網舉例。
如果我要使用大午安賬號登入午安空間網站,那麼這個大致流程如下:
使用Implicit Flow
- 首先午安空間會傳送授權請求給oidc-server
- 如果已經登入了,oidc-server會返回一個“證件”或者如果你沒登入會要求你登入,然後詢問你是否授權給午安空間某些許可權比如郵件地址等(當然午安這個例子裡面不存在,因為肯定都是全許可權)。
- 一旦你確定並授權了這次登入,oidc-server會傳送Acess-Token和ID Token(如果要求了),並跳轉回午安空間網站。(可以通過url附帶)
- (認證) 午安空間網站獲得ID-Token之後,使用oidc-server提供的公鑰解密驗證。
- 然後午安空間就可以通過之前得到的Access-Token去訪問oidc-server獲取使用者資訊了
午安網實現SSO的全流程設計
設計可能比較粗糙或者有問題,如果有問題希望評論一下幫我修正修正。
設計使用的是Implicit Flow。
單點登入
主動登出
沒啥好說的,客戶端清理自己的狀態,然後發出登出請求給oidc-server。
被動登出
這塊就找到了一個網上的例子
其利用oipc協議族裡的Discovery服務中提供的一個check_session_iframe介面。
核心原理是讓客戶端插入一個oidc-server頁面的iframe並週期性的檢查,當我在“午安空間”點選登出的時候,會發出登出請求給oidc-server並觸發oidc-server的站點清理自己的cookie,然後在之前客戶端中使用check_session_iframe這個隱藏的iframe可以檢測到這種變化,從而使得客戶端可以得知使用者已在再其他的應用的客戶端退出登入,這時候就清理自己客戶端的登入狀態。
例子中的客戶端程式碼
後記
這部分放的是下版本要加的或者完善的。
瞭解下Authorization Code Flow。
自動登入補充
如果只有上面的解決方案的話會存在一個問題,那就是如果我sso已登入,我到另一個網站比如午安影視,我需要點選登入之後才會出現登入狀態。也就是說沒有自動登入。
一個實現的方法是可以在一開始就去訪問oidc-server詢問是否已經登入,oidc-server的協議族Discovery提供一個介面。