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和登出页面之间对这个值作一些持久化的工做。

相关文章
相关标签/搜索