IdentityServer的登出就像刪除認證cookie同樣簡單,可是爲了完成一個完整的聯合簽名,咱們必須考慮將用戶從客戶端應用程序中(甚至多是上游的Identity提供者)登出。javascript
簡單的調用HttpContext的SignOutAsync方法就能刪除認證cookie,要使用該方法,你須要傳遞那個使用的認證方案(scheme,默認狀況下是IdentityServerConstants.DefaultCookieAuthenticationScheme,除非你更改過它):html
await HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);
或者你也可使用IdentityServer提供的這個更爲便利的擴展方法:前端
await HttpContext.SignOutAsync();
一般狀況下,應該提示用戶登出(意味着須要一個POST),不然攻擊者能夠將其連接到您的註銷頁面,從而致使用戶自動註銷。java
做爲signout這個總體動做的一部分,應該確保客戶端應用程序也獲得了用戶登出的信息,對於有服務端的客戶端,IdentityServer提供了對front-channel規範的支持;對於基於瀏覽器的javascript客戶端(例如SPA、React、Angular等),IdentitySever提供了對 session management 規範的支持。git
實際上,OIDC定義了三個規範來完成撤銷認證這個動做:github
其中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這一部分中重點有兩個信息:
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.實現的。
若是一個登出請求是被客戶端應用發起的,那麼客戶端首先會把用戶重定向到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和登出頁面之間對這個值作一些持久化的工做。