网络上有很多关于使用 JWT (Json Web Token
) 进行身份验证的信息。但是对于在多域环境中使用 JWT 令牌实现单点登录解决方案,我仍然没有找到明确的解释。
我为一家在不同主机上有很多网站的公司工作。让我们使用 example1.com 和 example2.com。我们需要一个单点登录解决方案,这意味着如果用户在 example1.com 上进行身份验证,我们希望他也自动在 example2.com 上进行身份验证。
使用 OpenId Connect 流程,我了解想要在 example1.com 上进行身份验证的用户将首先被重定向到 身份验证服务器(或 OP
:“OpenId提供者”)。用户在该服务器上进行身份验证,然后使用签名的 JWT 令牌将他重定向回原始 example1.com 站点。 (我知道还有另一个流程返回一个 中间令牌,它本身可以稍后交换为真正的 JWT 令牌,但我认为这对我们来说不是必需的)...
所以现在用户又回到了 example1.com 并通过了身份验证!他可以发出请求,在 Authentication
标头中传递 JWT 令牌,服务器能够验证签名的 JWT,因此能够识别用户。好的!
第一个问题:
JWT 令牌应该如何存储在客户端上?同样,有很多关于此的信息,人们似乎同意使用 Web Storage
是要走的路,而不是旧的 cookies
。我们希望 JWT 在浏览器重新启动之间保持不变,所以让我们使用 Local Storage
,而不是 Session Storage
...
现在用户可以重新启动他的浏览器,他仍然会在 example1.com 上进行身份验证,只要 JWT 令牌没有过期!
此外,如果 example1.com 需要向我们的另一个域发出 Ajax 请求,我知道配置 CORS 将允许这样做。但我们的主要用例不是跨域请求,而是具有单点登录解决方案!
因此,主要问题:
现在,如果用户访问 example2.com 并且我们希望他使用他已经拥有的 JWT 令牌进行身份验证,那么流程应该是什么? Local Storage
似乎不允许跨域访问,因此此时浏览器无法读取 JWT 令牌来向 example2.com 发出请求!
应该 :
用户再次被重定向到认证服务器?当用户对 example1.com 进行身份验证时,身份验证服务器可能已经在用户上设置了一个 cookie,因此这个针对 example2.com 的新身份验证请求可以使用该 cookie 来查看用户已经通过身份验证,并立即将他重定向回 example2.com使用相同的 JWT 令牌?
或者浏览器是否可以在 example2.com 上访问 JWT 令牌而无需再次访问身份验证服务器?我看到有跨存储解决方案,但这些解决方案被广泛使用吗?它们是跨域 SSO 环境的建议解决方案吗?
我们不想要任何花哨的东西,我们会对最常用的解决方案感到满意!
当用户未登录以请求凭据并发出新的身份验证令牌时,将用户重定向到中央身份验证服务是使用 oauth2 或 OpenId Connect 等知名协议的单点登录系统中的常见场景
但是,当跨域使用此架构时,主要缺点是由于同源策略,用户每次导航到其他域时都会被重定向和验证:访问令牌不能共享域之间(example2.com
无法访问 example1.com
的数据),因此目标域会将用户视为未经身份验证,将他重定向到中央 SSO 服务。
为了防止身份验证服务重新请求凭据,通常有一个会话 cookie(不是访问令牌),但是有一种技术可以使用浏览器 localStorage/cookies 和指向中间域的 iframe 跨域共享数据{ 1}
认证example1.com中的用户,将他重定向到sso.example.com中的认证服务器,认证后发出JWT并将其存储在该域的localStorage中。在此之后,将用户重定向到源域 example1.com 在 example2.com 中创建一个指向 sso.example.com 的 iframe。 sso.example.com 中的 iframe 读取 JWT 令牌并向父页面发送消息 父页面接收消息并获取附加令牌继续 SSO 流程
同源策略没有问题,因为 sso.example.com
可以访问其 localStorage,并且如果源域和目标域相互识别,则 iframe 和父页面之间的通信是允许的(请参阅 http://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage)
为了简化开发,我们最近在 https://github.com/Aralink/ssojwt 发布了带有 JWT 的跨域 SSO
此方法与 SSO 流完美兼容。这只是一种无需重定向即可共享身份验证令牌并在联合域时避免不必要的登录的方法
用户应再次重定向到身份验证服务器并获得一个新令牌 (JWT),该令牌专门针对 example2.com。这就是 OpenID Connect 和任何其他跨域联合 SSO 协议的工作原理。
不确定这是否能回答您的问题,但如果您的主要目标是单点登录,我认为一个简单的 reverse proxy 可以解决您的问题(至少是跨域存储问题)。
所以 example1.com example2.com
会变成类似的东西
example.com/example1
example.com/example2
(从用户方面来看,这通常更干净)
如果这不是一个选项,您可能必须进行设置,以便当用户在 1 个域中进行身份验证时,它使用 AJAX/隐藏 iframe 来创建与其他域的身份验证(如果必须通过 url 发送 1 次令牌)。
如果这不是一个选项,您可能不得不求助于用户名+pin,因为浏览器对跨域交互越来越严格。
不定期副业成功案例分享