现代浏览器中的跨站点身份验证,无需第三方 cookie

Cross-site auth in modern browsers without 3rd party cookies

提问人:luchaninov 提问时间:11/9/2023 更新时间:11/20/2023 访问量:187

问:

系统的几个部分位于不同的域(而不是子域)。我需要在用户登录任何域后对所有域的用户进行身份验证,而无需用户进行任何交互。

在过去,我在公共域中使用cookie。现在这是不可能的 - https://developer.chrome.com/docs/privacy-sandbox/chips/

然后我们将 iframe 与 LocalStorage 和 postMessage 一起使用到父窗口 - https://github.com/zendesk/cross-storage 。它最近也停止工作,因为现在不同的域对公共域有单独的 LocalStorage - https://developer.chrome.com/docs/privacy-sandbox/storage-partitioning/

Chrome 已经宣布了可能的解决方案:SharedStorage - https://developer.chrome.com/docs/privacy-sandbox/shared-storage/ 但是:

  • 它在 Safari 中不起作用(MacOS 和 iOS 用户对我们很重要)
  • 您必须以公司身份申请并注册您的域名(对我们来说不是问题,但对于舞台和开发环境来说不方便)

我只看到一个防弹的解决方案:

  • 将所有未经授权的用户重定向到公共域
  • common domain 生成随机令牌(或从 cookie/localstorage 中获取它(如果存在)并使用此令牌重定向回原始 URL
  • 域尝试使用此令牌进行身份验证
  • 如果未通过身份验证,则在登录/注册期间添加此令牌,以便下次自动登录用户
  • 在注销期间,删除此用户令牌,使其不再有效

这对用户来说是糟糕的 UI - 2 个额外的重定向;而且似乎过于复杂化。

也许有更好的解决方案可以在现代浏览器中工作?

身份验证 Google-Chrome Safari 本地存储 隐私

评论

0赞 Stefano Balzarotti 11/20/2023
您可以使用隐藏的iframe重定向到同一域,生成令牌,再次使用令牌重定向到其他域,将消息发布到主窗口
0赞 luchaninov 11/23/2023
@StefanoBalzarotti这种方法是行不通的,因为公共域的 iframe 将不同的 cookie 嵌入到不同的域。这就是 cookie CHIPS 的意义所在 developer.chrome.com/docs/privacy-sandbox/chips

答:

0赞 Julio Di Egidio 11/15/2023 #1

这个答案分为两部分,第一部分是关于高级设计的,第二部分是关于所讨论的具体技术问题。

高级设计

系统的几个部分位于不同的域(而不是子域)。 我需要在用户登录任何域后对所有域的用户进行身份验证 它们没有来自用户的任何交互。

我将讨论相对于应用程序域/站点的更抽象的概念:

在理想情况下,有多个应用程序加上一个单独的应用程序,专用于身份验证,更一般地说,专用于标识服务。(顺便说一句,请注意,授权,即处理可能与给定特定上下文的身份(用户)关联的特定角色和权限,实际上通常是特定于应用程序的,与身份服务无关。

我只看到一个防弹的解决方案:

  • 将所有未经授权的用户重定向到公共域

是的,但严格来说,重定向并不是必需的:您的标识服务可能只是公开 Web 服务,并且单个应用程序代表用户在后台与之交互。但重定向仍然是规范的解决方案,不仅是为了避免代码重复,而且特别是在相关的情况下,以便任何注册/登录/管理帐户体验在所有应用程序中保持统一。

  • 公共域生成随机令牌(或从 cookie/localstorage 获取它 如果存在),并使用此令牌重定向回原始 URL

生成新的令牌,句点。并将其存储在服务器上以备后用,特别是验证(见下文)。-- 对不起,我没有这方面的参考资料,但我会把它作为安全最佳实践,即登陆登录页面的经过身份验证的用户会自动注销(删除 cookie 和/或撤销与登录关联的任何存储令牌):这保持了用户流“干净”。

  • 域尝试使用此令牌进行身份验证

具体来说,一旦用户进行了身份验证,无论从哪里获得他们的身份验证令牌,他们都会将其与每个请求一起提交给任何应用程序:此时应用程序必须做的是验证令牌(这是标准术语,包括解密有效负载),它将再次通过利用身份服务公开的 Web 服务来做到这一点。

令牌通常直接在有效负载中携带身份信息:这个想法足以让任何特定应用程序能够唯一地识别用户,并在需要时继续进行任何授权。

这对用户来说是糟糕的 UI - 2 个额外的重定向;而且似乎过于复杂化。

事实上,重定向到登录页面,然后重定向回用户尝试访问的页面,是规范的解决方案,特别是如果用户明确注册/管理自己的帐户和个人资料:如果不需要,例如在 Intranet 上下文或机器对机器身份验证中,只需包装专用 Web 服务就足够了。

技术问题

说了这么多,对于架构概述,我特别应该提到一个技术问题,尤其是因为它明确地存在于问题中:

如果登录页面与应用程序本身位于不同的域中,则客户端如何将成功登录时生成的令牌转发到任何其他应用程序页面,因此我们会产生跨域限制。事实上,有几种方法可以解决这个问题,我只是简单地快速提及最常见的和我能想到的:

  • CORS 和跨域 cookie:也许是最干净、最适合我们目的的。https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS这可能与广告拦截器和类似程序有关,因为这些被认为是第三方 cookie:另一方面,要求用户添加与相关域相关的例外规则听起来并非不合理,只要他们确实想登录并使用应用程序......

  • 使用 HTTP 状态代码 307 重定向,用于将令牌发布回应用程序。https://www.rfc-editor.org/rfc/rfc9110.html#name-307-temporary-redirect https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307 我自己对此没有直接经验,但是人们,例如在 SO 上,说浏览器在允许重定向之前会要求用户进行确认,尽管我在官方文档中找不到对此要求的任何引用 [ADD:无论如何,声明“用户代理可以将位置字段值用于自动重定向“(我的强调),因此重定向可能不是自动的]:但是,如果大多数浏览器确实以这种方式运行,那么在我们的场景中,这很可能不是一个好的解决方案,它会无缘无故地造成糟糕的用户体验。

  • 返回一个 HTML 页面,其中包含包含标记的隐藏字段,然后由 JS 在页面加载时自动提交。 我认为这也是一个可以接受的解决方案,就用户体验而言,它确实与通常的客户端重定向没有太大区别,页面显示“在 3,2,1 中自动重定向......秒:如果不起作用,请单击此链接”。潜在的缺点是,这在禁用 JS 的情况下不起作用,另一方面,如上所述,在禁用 JS 的情况下浏览网页的用户当然不会不习惯单击链接或按下提交按钮以继续。

  • 在 iframe 中打开登录页面,并使用 window.postMessage API 跨域交换结果令牌。https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage这个需要更多的客户端编码,它也具有前面提到的所有基于 JS 的解决方案的局限性,但是,在合理期望用户启用 JS 的情况下,这个也是一个可行的解决方案,根据我的经验,它运行良好。

  • 共享本地存储和类似的实验性功能https://developer.chrome.com/docs/privacy-sandbox/shared-storage/我认为任何尚未被浏览器广泛支持的“特殊”功能在这里都不可行:一个例外是可以完全控制正在使用的浏览器的上下文,但我认为这是一种正在消失的场景:在我们这个普遍访问的时代,无论如何都可以随时随地工作。

评论

0赞 luchaninov 11/23/2023
是的,我只有一个身份验证的真实来源 - 在公共领域。但是如何在没有用户交互和没有重定向的情况下自动登录用户呢?(你写了“虽然重定向不是严格需要的”)
0赞 Julio Di Egidio 11/23/2023
你说“自动登录”,我不知道你到底是什么意思。事实是,您现在以更严格的要求重新制定/扩展问题,可能考虑我提到的流程和变体(例如,谁需要身份验证,是否涉及帐户管理或普通登录,是否可以接受登录页面不由身份服务本身提供, 您所说的“自动登录”实际上是什么意思,等等),或者我发现不可能给出比上述更具体的建议。
0赞 ste-fu 11/20/2023 #2

在我看来,您所描述的内容与 OAuth 2.0 授权流程或 Open Id Connect (OIDC) 非常相似

与其尝试一个完全自定义的系统,不如重新构建你的系统以遵循一个开放的 Web 标准,这样你就不太可能在未来的更改中犯规。

是的,您需要创建自己的身份服务器,它确实涉及重定向,但是作为用户和开发人员跨多个系统使用 Microsoft Azure / Azure AD 实现,这并不是一个糟糕的用户体验。

有许多博客、教程或第三方产品支持这些流程。搜索“OAuth 2”或“Open ID Connect”+您选择的语言/框架将帮助您入门

评论

0赞 luchaninov 11/23/2023
当用户来到网站时,我不知道用户事件是否有该帐户。使用重定向解决方案,我必须重定向所有用户进行自动登录或等到他们按下“登录”按钮