调用全局退出无法注销应用系统的用户会话
# 问题描述
应用系统采用Oauth2、OIDC等标准协议集成IDaaS认证服务,管理员在IDaaS企业中心的应用配置中添加应用系统的退出地址后,应用开发者经常遇到以下场景,调用全局退出时无法注销应用系统的用户会话。
- 采用IDP-initialed发起的Sign out:用户首先登录进入IDaaS用户中心,然后访问权限范围内的应用系统App1、App2,当用户在IDaaS用户中心点击统一退出后,仅注销了SSO会话信息,但是没有同步注销应用系统的用户会话。
- 采用SP-initiated发起的Sign out:用户首先通过IDaaS认证后访问目标应用系统App1、然后继续访问App2/3/N,当用户在某应用系统中点击退出时(该应用已集成全局退出),除了成功注销SSO会话和当前应用系统的用户会话外,但是没有同步注销其它业务系统的用户会话。
# 问题原因
1.应用系统配置的退出地址是HTTP协议,而非HTTPS协议。
因IDaaS服务是Https协议请求,当通过IDaaS的统一退出页面调用应用系统Http协议的退出地址时,浏览器会认为这个请求是不安全的,浏览器禁止该请求,造成注销应用系统的用户会话失效。
2.在跨站请求下,IDaaS调用应用系统退出地址时,应用系统不能获取到当前用户在该系统的cookie。
在跨站请求下,竹云IDaaS调用应用系统的退出地址会被浏览器限制携带Cookie,应用系统无法识别登录当前业务系统的用户身份,造成注销业务系统的用户会话失败。
# 解决方案
1.应用系统必须使用HTTPS协议访问
2.跨站场景下,服务器的cookie属性SameSite设置为“None; Secure”,声明无论是否跨站都可以发送 Cookie
采用Java HttpResponse.addHeader()设置Cookie示例:
response.addHeader("Set-Cookie", "CookieName=CookieValue;SameSite=None;Secure");
1
2
3
2
3
注意点:
- HTTP接口不支持 SameSite=None。如果你想加 SameSite=None 属性,那么该 Cookie 就必须同时加上 Secure 属性,表示只有在 HTTPS 协议下该 Cookie 才会被发送。
- 新版本的Safari默认开启“阻止跨网站跟踪”,禁止跨站访问第三方Cookie。换句话说即使应用服务器设置SameSite=None; Secure,Safari浏览器也不允许携带Cookie请求,有关说明可参考:Safari禁止第三方Cookie无法获取用户登录状态
3.使用Nginx或其他网关工具进行Proxy操作,使跨站请求变为同站请求。
# 相关参考
# SameSite属性
SameSite是 HTTP 响应头 Set-Cookie的属性之一。它允许声明该 Cookie 是否仅限于第一方或者同一站点上下文。
SameSite 可以有下面三种值:
- Strict 仅允许一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL 完全一致。
- Lax 允许部分第三方请求携带 Cookie。
- None 无论是否跨站都会发送 Cookie。
之前默认是 None 的,Chrome80 后默认是 Lax。
Lax的情况见下表:
请求类型 | 示例 | 正常情况 | Lax |
---|---|---|---|
链接 | <a href="..."></a> | 发送 Cookie | 发送 Cookie |
预加载 | <link rel="prerender" href="..."/> | 发送 Cookie | 发送 Cookie |
GET 表单 | <form method="GET" action="..."> | 发送 Cookie | 发送 Cookie |
POST 表单 | <form method="POST" action="..."> | 发送 Cookie | 不发送 |
iframe | <iframe src="..."></iframe> | 发送 Cookie | 不发送 |
AJAX | $.get("...") | 发送 Cookie | 不发送 |
Image | <img src="..."> | 发送 Cookie | 不发送 |
当sameSite为Lax时,post、iframe、ajax、image的跨站请求都不会发送cookie。