基于 JWT 的跨域身份验证单点登录流

网上有很多关于使用 JWT (Json Web Token)进行身份验证的信息。但是我仍然没有找到一个清晰的解释,说明在对 多域环境中的单点登录解决方案使用 JWT 令牌时流应该是什么样的。

我在一家公司工作,这家公司在不同的主机上有很多网站。让我们使用 Example1.comExample2.com。我们需要一个单点登录解决方案,这意味着如果一个用户在 Example1.com上进行身份验证,我们希望他也在 Example2.com上进行身份验证,这是自动的。

通过使用 OpenId 连接流,我了解到希望在 Example1.com上进行身份验证的用户将首先被重定向到 认证服务器(或者 OP: “ OpenId Provider”)。用户在该服务器上进行身份验证,然后用签名的 JWT 令牌将用户重定向回原来的 Example1.com站点。(我知道还有一个返回 中间代币中间代币的流,它本身可以在以后交换真正的 JWT 令牌,但我认为我们不需要这样做) ..。

所以现在用户回到了 Example1.com上,并且通过了身份验证!他可以发出请求,在 Authentication头中传递 JWT 令牌,服务器能够验证签名的 JWT,因此能够识别用户。漂亮!

第一个问题:

如何将 JWT 令牌存储在客户机上?关于这一点还有很多信息,人们似乎都认为使用 Web Storage比使用老式的 cookies更好。我们希望 JWT 在浏览器重启之间是持久的,所以让我们使用 Local Storage,而不是 Session Storage..。

现在用户可以重新启动浏览器,只要 JWT 令牌没有过期,他仍然会在 Example1.com上进行身份验证!

另外,如果 Example1.com需要向我们的另一个域发出 Ajax 请求,我理解配置 CORS将允许这样做。但是,我们的主要用例不是跨域请求,它有一个 单点登录解决方案

因此,主要的问题是:

现在,如果用户访问 Example2.com,我们希望使用他已经拥有的 JWT 令牌对他进行身份验证,那么流应该是什么呢?Local Storage似乎不允许跨域访问,因此此时浏览器无法读取 JWT 令牌来向 Example2.com发出请求!

应该:

  • 用户再次被重定向到 认证服务器 身份验证服务器 可能已经在用户上设置了一个 cookie,因此这个新的 Example2.com身份验证请求可以使用这个 cookie 查看用户是否已经通过身份验证,并立即将用户重定向回 Example2.com 使用相同的 JWT 令牌?
  • 或者浏览器可以在 Example2.com上访问 JWT 令牌而不必再次访问 认证服务器吗?我看到有 交叉存储解决方案,但是它们被广泛使用吗?它们是否是跨域 SSO 环境的建议解决方案?

我们不想要任何花哨的东西,我们会很高兴与最常用的解决方案!

73352 次浏览

应该再次将用户重定向到身份验证服务器,并获得一个新的令牌(JWT) ,这是专门针对 example2.com 的令牌。这就是 OpenIDConnect 和其他跨域联合 SSO 协议的工作方式。

在使用 oauth2或 OpenId Connect 等众所周知的协议的单点登录系统中,当用户没有登录以请求凭证并发出新的身份验证令牌时,将用户重定向到集中式认证服务

然而,当这种模式跨域使用时,主要缺点是,由于同源策略,用户每次导航到其他域时都会被重定向和身份验证: 访问令牌不能在域之间共享(example2.com不能访问 example1.com的数据) ,因此目标域将把用户视为未经身份验证的用户,将他重定向到中央 SSO 服务。

为了防止身份验证服务重新请求凭证,通常使用会话 cookie (而不是访问令牌) ,但是有一种技术可以使用浏览器 localStorage/cookies 和指向中间域 sso.example.com的 iframe 跨域共享数据

  1. 要对 example1.com中的用户进行身份验证,请将其重定向到 sso.example.com中的身份验证服务器,在进行身份验证后发出 JWT,并将其存储在此域的 localStorage 中。然后,将用户重定向到原域 example1.com

  2. example2.com中创建一个指向 sso.example.com的 iframe。Example.com 中的 iframe 读取 JWT 令牌并向父页面发送消息

  3. 父页面接收消息并获取附加的令牌,以继续 SSO 流

同源策略没有问题,因为 sso.example.com可以访问它的 localStorage,并且如果起源域和目标域相互识别,则允许 iframe 和父页之间的通信(参见 http://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage)

为了简化开发,我们最近发布了一个 与 JWT 在 < a href = “ https://github.com/aralink/ssojwt”rel = “ norefrer”> https://github.com/aralink/ssojwt 交叉域 SSO

这种方法与 SSO 流完全兼容。它只是一种在没有重定向的情况下共享身份验证令牌的方法,并且在联合域时可以避免不必要的登录

不确定这是否回答了您的问题,但是如果您的主要目标是单点登录,我认为一个简单的 反向代理服务器将解决您的问题(至少是跨域存储)。

那么 Example1.com Example2.com

会变成

Example.com/example1

Example.com/example2

(从用户的角度来看,这通常更干净)

如果这不是一个选项,您可能必须设置,以便当用户在1个域中进行身份验证时,它使用 AJAX/隐藏 iframe 来创建与其他域的身份验证(如果必须的话,通过 URL 发送1时间令牌)。

如果这不是一个选项,你可能不得不求助于用户名 + 别针,因为浏览器越来越严格的跨域交互。