如何在基于 JWT 的单点登录身份验证架构中实现注销?
Posted
技术标签:
【中文标题】如何在基于 JWT 的单点登录身份验证架构中实现注销?【英文标题】:How to implement Logout in a JWT based Single Sign On authentication architecture? 【发布时间】:2016-02-27 07:23:30 【问题描述】:我正在尝试了解如何使用 Json Web 令牌在单点登录架构中实现注销功能。
假设我们有:
example1.com
example2.com
authserver.com
当用户必须在 example1.com
上进行身份验证时,他会被重定向到 authserver.com
,这会验证用户凭据,创建签名的 JWT 令牌并使用此令牌将用户重定向回 example1.com
。然后example1.com
将设置一个cookie(或LocalStorage 密钥),并且只要令牌未过期,用户就会在example1.com
上进行身份验证。无需再调用authserver.com
来识别用户。
然后用户转到参与 SSO 架构的example2.com
。用户也需要在那里进行身份验证,因此example2.com
还将用户重定向到authserver.com
,它可以识别用户(使用它第一次设置的 cookie),创建一个新的 JWT 令牌并自动将用户重定向回 @ 987654333@。然后,example2.com
将设置一个 cookie(或 LocalStorage 密钥),并且只要令牌未过期,用户就会在 example2.com
上进行身份验证。无需再调用authserver.com
来识别用户。
现在,如何实现“注销”功能?
如果用户在example1.com
上注销,example1.com
上的 JWT 令牌将被删除,用户不应再在那里进行身份验证。但是一旦他尝试到达保护区,example1.com
会将他重定向到authserver.com
,用户将被识别并自动再次登录……即使他刚刚注销!
问题 1) 所以我猜当用户在example1.com
上注销时,必须调用authserver.com
以删除authserver.com
设置的cookie em> 这样用户就不会再自动登录了?
问题 2) 如果是这样,example2.com
呢?用户还应该在那里进行身份验证吗?如果没有,建议的流程是什么,以便example2.com
知道它为用户拥有的 JWT 令牌不再有效?
【问题讨论】:
【参考方案1】:或者,您也可以在没有 openid 的情况下实现跨域 SSO,仅在客户端使用 JWT,例如谷歌网络应用程序。
优点是您不需要将用户重定向到服务器即可知道用户是否已登录。注销和 JWT 更改可以在选项卡之间自动同步。
Authserver.com 将 JWT 返回给 example1 后,将其存储在 localStorage 中,但通过 iframe 使用中间域 sso.example.com。在 example1 和 example2 中包含此 iframe(指向 sso.example.com)。 iframe 将读取 JWT 并向包含令牌的页面发送消息。
当用户注销或更改活动用户时,iframe 还可以向父级发送消息,因此您可以同步所有站点(如果需要)
CORS 没有问题,因为 sso.example.com 可以访问其 localStorage。如果源和目的地被识别,则允许 iframe 之间的通信(请参阅http://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage)
为了简化开发,我们最近在https://github.com/Aralink/ssojwthttps://github.com/Aralink/ssojwt发布了一个使用 JWT 的跨域 SSO
将您的问题总结为这种架构 1)清理localStorage中的JWT并发送一个javascript事件 2) 监听事件并决定做什么
【讨论】:
浏览器似乎开始阻止第三方 cookie/停止跨域跟踪,加载到 iframe 中的服务器将无法访问该服务器的 cookie 和 localStorage。因此,这种方法将不再有效。链接:theverge.com/2020/1/14/21064698/…【参考方案2】:1) https://openid.net/specs/openid-connect-session-1_0.html#RPLogout 是一个规范(对于不同的策略还有其他规范),也可以退出 authserver。它定义了您的 example1.com 将重定向到的 end_session_endpoint
;请注意,authserver 将用户注销并可以重定向回 RP 的 post_logout_redirect_uri
。
2) 我认为这取决于你想要它做什么。您可能不想终止 example2.com 会话,在这种情况下 example2.com 会继续。 example2.com 的 JWT 仍然有效。如果您想注销所有客户端,这有点复杂但可能。在我的项目中,我们想要注销一个客户端和身份验证服务器。
【讨论】:
非常有趣,谢谢!但是我不确定为什么用户在注销时应该被重定向到 OP……我想不出任何发生在我身上的真实案例。当我单击“注销”链接时,我想直接注销,而不是重定向到另一个站点来确认操作!此外,即使用户被重定向到 OP 并确认他想注销,他仍可能在另一个站点上进行身份验证,例如example2.com
。所以在我看来,结果有点奇怪。不过,如果 example2.com
有办法知道其令牌不再有效,则此流程是有意义的。
我想知道后端服务器 example1.com
是否会出现问题,通过传递 JWT 令牌来清除 OP 上的 end_session_endpoint
自身会话...因此无需将用户重定向到那里。我错过了什么重要的东西吗?
一个 OP 实现,如果您同时提供 JTW 和 post_logout_redirect_uri,IdentityServer3 (identityserver.github.io/Documentation/docsv2/endpoints/…) 重定向只会立即将您重定向回客户端。如果一切正常,您甚至都看不到 OP。还有其他规范可以做类似的事情(实际上 IdentityServer3 昨天刚刚实现了另一个:openid.net/specs/openid-connect-logout-1_0.html)但诀窍是需要清除 OP 上的浏览器 cookie...我想不出你会怎么做不以某种方式在 OP 上执行此操作)
我猜对 OP 的后端调用可能会使与用户 cookie 关联的“会话”无效,所以这个 cookie 在不被删除的情况下不再有效。但我同意,如果它是快速重定向/重定向回来,没关系。我之所以问是因为您发布的 OpenID 规范是:At the logout endpoint, the OP SHOULD ask the End-User whether he wants to log out of the OP as well. If the End-User says "yes", then the OP MUST log out the End-User.
。但这是应该而不是必须,所以我想自动注销+即时重定向也可以...以上是关于如何在基于 JWT 的单点登录身份验证架构中实现注销?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Account Manager 在 Android 中实现 JWT 身份验证