SSO 和嵌入

我们部署了一个 Discourse 实例,并配置了 SSO(使用 SAML/Shibboleth),同时设置允许在另一个同样使用相同 SSO 的子域名上嵌入内容。

以下是我遇到的问题:

  1. 用户访问子域名 X 上的一个页面,该页面嵌入了托管在子域名 Y 上的 Discourse 主题。
  2. 用户被重定向到子域名 Z 进行 SSO 登录,随后又被重定向回子域名 X。
  3. 子域名 X 上的页面加载 JavaScript 嵌入文件,该文件创建一个 iframe 以尝试加载论坛主题。然而,Discourse(子域名 Y)将 iframe 重定向到子域名 Z 进行 SSO。由于用户已经登录,系统会将其重定向回 Discourse 嵌入 URL。但这会导致 400“嵌入错误”,因为此时 Referer URL 来自子域名 Z(SSO 子域名),而不是子域名 X(已批准/列入白名单用于嵌入的域名)。Discourse 返回的消息是:“Referer 未发送,或与以下任何主机不匹配”。
  4. 刷新页面后,一切正常工作(即论坛主题成功加载),这可能是因为浏览器现在拥有有效的会话 Cookie,从而无需再重定向到 SSO 子域名。

有什么方法可以彻底解决这个问题吗?目前我设置了一个非常糟糕的变通方案:首先尝试将论坛主题加载到一个隐藏的 iframe 中,然后等待 1 秒,再将其加载到用户可见的实际页面中。

任何帮助或建议都将不胜感激!

经过进一步研究,我在想是否有一种稍微不那么“黑客”的解决方案,即采用 @simon 在此帖子中描述的方法:Automatically login via SSO - #4 by simon

  1. 启用“SSO 允许所有返回路径”设置
  2. 在我的页面上添加一个隐藏的 iframe,加载 https://discourse.example.com/session/sso?return_path=path_to_mypage.html
  3. 当用户已登录(无需交互,因为用户已通过 SSO 在父页面中登录到应用)且 iframe 被重定向到 mypage.html 时,它可以通过 postMessage() 向父页面通信用户已登录 Discourse,并触发脚本嵌入论坛主题。

这仍然看起来不是理想的解决方案,因为它会产生额外的往返(上述过程仅在用户尚未登录 Discourse 时才有必要)。

在我看来,理想的解决方案是, somehow 能够在通过 SSO 重定向时保留嵌入页面的 referer URL。

编辑:我在此帖子中实现了上述改进后的“黑客”方案,至少可以说,它比我在原帖中描述的原版“黑客”方案效果好得多。