IdentityServer4【Topic】之登出

Sign-out 登出

IdentityServer的登出就像刪除認證cookie同樣簡單,可是爲了完成一個完整的聯合簽名,咱們必須考慮將用戶從客戶端應用程序中(甚至多是上游的Identity提供者)登出。javascript

Removing the authentication cookie刪除認證cookie

簡單的調用HttpContext的SignOutAsync方法就能刪除認證cookie,要使用該方法,你須要傳遞那個使用的認證方案(scheme,默認狀況下是IdentityServerConstants.DefaultCookieAuthenticationScheme,除非你更改過它):html

await HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);

或者你也可使用IdentityServer提供的這個更爲便利的擴展方法:前端

await HttpContext.SignOutAsync();

一般狀況下,應該提示用戶登出(意味着須要一個POST),不然攻擊者能夠將其連接到您的註銷頁面,從而致使用戶自動註銷。java

Notifying clients that the user has signed-out通知客戶端用戶已經登出

做爲signout這個總體動做的一部分,應該確保客戶端應用程序也獲得了用戶登出的信息,對於有服務端的客戶端,IdentityServer提供了對front-channel規範的支持;對於基於瀏覽器的javascript客戶端(例如SPA、React、Angular等),IdentitySever提供了對 session management 規範的支持。git

實際上,OIDC定義了三個規範來完成撤銷認證這個動做:github

  1. Session Management :可選。Session管理,用於規範OIDC服務如何管理Session信息。
  2. Front-Channel Logout:可選。基於前端的註銷機制。
  3. Back-Channel Logout:可選。基於後端的註銷機制。

其中Session Management是OIDC服務自身管理會話的機制;Back-Channel Logout則是定義在純後端服務之間的一種註銷機制,應用場景很少,這裏也不詳細解釋了。這裏重點關注一下Front-Channel Logout這個規範(http://openid.net/specs/openid-connect-frontchannel-1_0.html),它的使用最爲普遍,其工做的具體的流程以下(結合Session Management規範):後端

(上圖來自:https://www.cnblogs.com/linianhui/p/openid-connect-extension.html)瀏覽器

在上圖中的2和3屬於session management這個規範的一部。其中第2步中,odic的退出登陸的地址是經過Discovery服務中返回的end_session_endpoint字段提供的RP的。其中還有一個check_session_iframe字段則是供純前端的js應用來檢查oidc的登陸狀態用的。安全

4567這四步則是屬於front-channel logout規範的一部分,OIDC服務的支持狀況在Discovery服務中也有對應的字段描述:服務器

4567這一部分中重點有兩個信息:

  1. RP退出登陸的URL地址(這個在RP註冊的時候會提供給OIDC服務);
  2. URL中的sessionid這個參數,這個參數通常是會包含在idtoken中給到OIDC客戶端,或者在認證完成的時候以一個獨立的sessionid的參數給到OIDC客戶端,一般來說都是會直接把它包含在IDToken中以防止被篡改。

Front-channel server-side clients 


在front-channel規範中,爲了從帶有服務端的client上登出用戶,identityserver上面的登出頁面必須渲染一個<iframe>來通知client客戶已經登出。但願被通知的客戶端必須設置了FrontChannelLogoutUri 這個配置。IdentityServer跟蹤用戶登入的那個客戶端,而且在IIdentityServerInteractionService (查看詳情)上面提供了一個GetLogoutContextAsync 的API,這個API返回一個LogoutRequest對象,它帶有一個SignOutIFrameUrl屬性,你的登出頁面必須呈現爲<iframe>(原文是:This API returns a LogoutRequest object with a SignOutIFrameUrl property that your logged out page must render into an <iframe>.我這個翻譯很拗口,不知道翻譯的對不對,請指正)

Back-channel server-side clients


要經過back-channel規範從服務器端客戶端應用程序中籤出用戶,identityserver中的SignOutIFrameUrl端點將自動觸發服務器到服務器的調用,將簽名的簽出請求傳遞給客戶端。這意味着,即便沒front-channel客戶端,身份服務器中的「註銷」頁面仍然必須呈現如上所述的SignOutIFrameUrl。但願被通知的客戶端必須有BackChannelLogoutUri配置值集。

Browser-based JavaScript clients

考慮到 session management 規範的設計方式,在identityserver中沒有什麼特別的東西,須要作的是通知這些客戶已經登出。可是,客戶端必須在check_session_iframe上執行監控,這是由oidc-client JavaScript library.實現的。

Sign-out initiated by a client application客戶端應用發起的登出請求

若是一個登出請求是被客戶端應用發起的,那麼客戶端首先會把用戶重定向到end session endpoint。在處理從end session endpoint經過重定向到登出頁面這件事可能須要保持一些臨時的狀態(state)(好比客戶端登出的重定向uri)。這個狀態或許對於登出頁面是有用的,而且state的標誌符( the identifier for the state)也經過一個logoutid的參數傳遞給了logout頁面。

 interaction service 上面的GetLogoutContextAsync API能夠用來加載這個state。返回的LogoutRequest對象上的ShowSignoutPrompt屬性指示簽出的請求是否已認證過,而且所以它不提示用戶簽出是安全的。

默認狀況下這個state是經過logoutid的值做爲一個被保護的數據結構來管理的,經過實現IMessageStore<LogoutMessage>並將其註冊到DI,能夠在end session endpoint和登出頁面之間對這個值作一些持久化的工做。

相關文章
相關標籤/搜索