【问题标题】:Feasibility of SSO with SameSite Lax cookies, only?仅使用 SameSite Lax cookie 进行 SSO 的可行性?
【发布时间】:2020-12-03 17:39:59
【问题描述】:

背景

我今天正在玩弄为我的 cookie 实现 SameSite 的方面。我已经有了HttpOnlySecure,所以我认为这可能没什么大不了的。

为什么会坏

好吧,结果是,一旦我实施了这个设置,很多东西就坏了。 SameSite=LaxSameSite=Strict 都发生了这种情况。我做了一些研究,发现这是因为 SSO 容易在使用 LaxStrict 的 SameSite 设置(而不是 None)时损坏:

我的主要浏览器(Iron 70)基于 Chromium 70,所以我之前从未遇到过在 2 月份向 Chrome 80 用户推出的更改,据说默认没有 SameSite 值的 cookie 为 Lax。我安装了最新的 Google Chrome Portable 来检查它,有趣的是,该功能目前(谢天谢地)默认为 SameSite=Lax,因为它可能已经习惯了 - 我的网站只有在我显式启用以下标头:

Header edit Set-Cookie ^(.*)$ $1;SameSite=Lax

这似乎是因为没有明确的SameSite,Chromium 默认将其视为"LAX + POST w/ 2-minute rule"(我正在快速测试,所以在 2 分钟内)。

不过,即使使用Lax,我的所有单点登录都已损坏,并且我的实时聊天不再起作用 - 无论是使用 Websockets 还是 XHR 请求。当我尝试进行单点登录时,不知何故我最终退出了主网站,这也没有多大意义 - 基本上,一切都搞砸了。

  1. 有没有希望让 XHR 或 Websockets 再次与 Lax 一起工作?我在chat.example.com 上聊天,但我也允许在sub.someotherdomain.org 的侧面板中访问它。我的猜测是这里的答案是,解决它的唯一方法是在同一个域上提供一个 URL,Apache 只是在幕后指向同一个脚本。烦人,但它可以完成 - 但还有其他方法吗?

  2. 我更大的问题是:单点登录本质上与LaxStrict 不兼容吗?我并没有真正找到太多这样的方式。所有文章似乎都将使用Lax 破坏 SSO 视为不可避免,甚至还有一些图表解释了它为什么它会破坏,但 SSO 必须是这样吗?

主流解决方法

大多数网站都说要使用SameSite=None 来解决这个问题并强制所有用户代理中的旧行为。从技术上讲,这是可行的,但我想知道是否有任何希望能够使用 Lax 代替?如何在不屈服于SameSite=None 的情况下使其工作?

【问题讨论】:

  • “Strict 对我来说似乎没什么用,因为如果一个指向您网站页面的链接被发布到论坛上,当人们点击它时,他们突然就不再登录了” - 我认为您对 Strict 的理解在这里不正确。 MDN 将其表述为,“Cookie 将仅在第一方上下文中发送,不会与第三方网站发起的请求一起发送。” - 首先在顶部浏览上下文中打开链接 -派对,[…]
  • […] 并且仅单击链接也不是由第 3 方站点发起的请求。 (这将适用于通过 JS 发出的对脚本、样式表、图像或后台请求等嵌入式资源的请求。)
  • @CBroe 啊,感谢您的澄清,尽管在我测试时,我似乎确实注意到了这一点。那我需要多玩一点。无论如何,CSS、XHR 和 WS 似乎都已退出 Strict,也许还有 Lax。

标签: post cookies get single-sign-on samesite


【解决方案1】:

TL;DR - 是的,您可以使用SameSite=Lax(但不能使用SameSite=Strict)并且不会破坏 SSO!

SameSite cookie 有两点需要注意:

  • Lax 禁止使用POST 进行跨站请求
  • Strict 还禁止使用GET 进行跨站请求

有用的总结:

来源:https://www.wst.space/cookies-samesite-secure-httponly/

Strict 根本行不通,因为它会阻止任何类型的跨站点请求发送 cookie,这使得 SSO 完全不可能。 Strict 甚至不是一个可行的候选人。

这给我们留下了LaxNone(这是迄今为止的默认设置,并且正在慢慢被Lax 取代)。

  1. 有没有希望让 XHR 或 Websockets 再次与 Lax 一起工作?我在chat.example.com 聊天,但我也允许访问 在sub.someotherdomain.org 的侧面板中。我的猜测是 此处的答案是,解决它的唯一方法是 URL 在 Apache 简单指向的同一域上可用 幕后的相同脚本。烦人,但它可以完成 - 但是 还有其他方法吗?

这里最好的解决方案是在后台重写 URL,这样您就不需要维护重复的资源。使用 Apache 的 mod_rewrite 重写 URL 或简单地执行 include('path/to/file.php') 将是一个简单的解决方案。返回的 content 将完全相同 - 但如果需要发送 Lax cookie,则浏览器必须将它们发送到当前域的祖先域。

  1. 我更大的问题是:单点登录是否与LaxStrict 天生不兼容?

不,幸运的是,没有!

我并没有真正找到太多的方法 这。所有文章似乎都将使用Lax 破坏 SSO 视为 不可避免,甚至还有一些图表可以解释为什么 中断,但 SSO 必须这样吗?

确实很多 SSO 页面确实SameSite=Lax 中断 - 但这种失败不是 em> 不可避免 - 它是特定于实现的。让我们将原始方法与兼容SameSite=Lax cookie 的修改方法进行比较。

原始 SSO 流程(需要 SameSite=None

  1. 用户导航到sub.example.org - 当前未登录,因为此站点上未设置 cookie
  2. 页面检测到未登录并自动重定向到example.com 上的 SSO 页面 - 如果用户未在此处进行身份验证,它会重定向回来并提供用户名/密码提示。如果用户 已通过身份验证,则继续。
  3. example.com 上,读取用户的会话数据并为SSO 调用创建一个唯一令牌。将令牌转储到数据库中,然后使用插入的令牌 POST 回原始站点。
  4. 返回sub.example.org,读取已发布的令牌并在数据库中查询该令牌,并从中检索用户 ID。
  5. sub.example.org 上的本地会话中设置用户 ID - 现在会话按预期工作,因为 $_SESSION['mysession']example.comsub.example.org 上返回相同的信息(因为用户 ID 永远不会改变,技术上这些是重复的 cookie)。

这将与SameSite=Lax 中断。为什么?因为对身份验证器的原始请求使用的是 POST 请求 - 这是针对外部域的 - 而 SameSite=Lax SameSite=Strict 和跨域 @ 都认为这是危险的987654359@s 不会将 cookie 发送到目的地。因此,cookie 不可用,并且身份验证器不知道哪个用户已通过身份验证,因此它无法在回发之前为该用户创建临时令牌。这就是为什么这不起作用。

然而,这里需要注意的重要一点是POST 请求没有发送任何敏感数据(至少在上述实现中)。它只是要求进行身份验证 - 它甚至没有任何敏感数据要发送!

那么,为什么我们首先要POSTing?回想一下SameSite=Lax 允许一级GET 导航(SameSite=Strict 不允许)。因此,我们可以通过简单地使用GET 而不是POSTinitial 重定向only 来利用这一点。

解决方法

如何在不屈服于 SameSite=None?

方法如下。因为Lax 允许顶级GET 但不允许POST(这被认为是“危险的”),所以初始重定向使用GET 而不是POST。

自相矛盾的是,GET 可能不如POST 安全,但敏感数据(用户的令牌)仅在最终重定向时发送回请求身份验证的站点 - 初始重定向仅显示“嘿,我“正在请求身份验证”。

这是支持这种可能性的a brief excerpt,其结论是:

总之,IdP应该继续在其 cookie 浏览器默认为 SameSite=Lax(目前在 Chrome 78-81 和 Firefox 72 设置了相同的站点默认标志)。 通常,我们只看到 IdP 本身在 JSESSIONID 中断时 设置为 SameSite 'Strict',除了当 明确尝试使用旧版本的 Safari 设置 SameSite=None 在 MacOS https://bugs.webkit.org/show_bug.cgi?id=198181)。然而关于 要实现单点登录,您可能会看到操作降级,并且 出现以下可能性:

初始重定向需要使用授权域上的 cookie,而请求授权的域并不请求 cookie - 它是设置一个基于 POST 的 cookie。所以这在理论上应该与Lax 一起工作,因为在最终的POST 请求中不需要cookies - 只有最初的请求。最终的 POST 重定向将无法在该请求上发送 cookie...但它不需要 - 我们在 POST 请求本身中发送令牌,并基于此设置cookie。天才!

修订的 SSO 流程

原始 SSO - 需要 SameSite=None

  1. 请求者POSTs 到身份验证提供者
  2. 身份验证提供程序接收 cookie(需要 None 或未定义的 SameSite)并创建临时令牌
  3. 身份验证提供者使用令牌重定向回请求者,该令牌对其进行验证并创建会话 cookie

修订的 SSO - 与 SameSite=Lax 兼容:

  1. 请求者GETs 到身份验证提供者
  2. 身份验证提供程序接收 cookie(因为现在这是 GET,而不是 POST)并创建临时令牌
  3. 身份验证提供者使用令牌重定向回请求者,该令牌对其进行验证并创建会话 cookie

一个区别——就是这样——在初始重定向时是GET,而不是POST。这是有效的,因为初始重定向不包含敏感信息。这个POST 很可能是GET。通过使其成为一个,我们可以提高整个会话 cookie 以及任何记住我 cookie 的安全级别 - 不错!

我已经在 Chromium 70 和 Chrome 84 中测试了这个,严格标志和第三方 cookie 被阻止(所以没有“Lax + POST”,它只是“Lax”)。这确实有效。您还可以将任何记住我的 cookie 设置为 SameSite=Lax - 如果身份验证器需要使用它们来自发创建会话,因为没有会话正在进行,只要重定向存在 @ 987654391@ 而不是 POST - 所以我们很好!

结论

SSO 可以使用Lax。显然,XHR、动态 CSS、websockets 等不会,但这些可以被简单地代理在原始域后面。通过在初始重定向中使用GET 而不是POST,您可以使用带有SameSite=Lax 的cookie。

更复杂的 SSO 流程可能会有所不同 - 我在这里给出的只是一个非常简单的 SSO 示例。但是,SSO 和 SameSite=Lax并非相互不兼容 - 您可以通过稍微调整 SSO 设置来使其正常工作,如果您根据需要进行其他更改,不会有任何问题。

请注意,您可以仍然与SameSite=Strict 进行会话 - 如果您的整个网站都在一个主机名上并且它非常敏感,我建议您改为这样做。但是,如果你需要做 SSO,你至少可以使用SameSite=Lax(当然不能使用Strict)。

【讨论】:

    猜你喜欢
    • 2020-05-23
    • 2020-06-07
    • 2021-08-21
    • 2019-01-14
    • 1970-01-01
    • 2020-04-14
    • 2020-06-25
    • 2021-08-20
    • 1970-01-01
    相关资源
    最近更新 更多