使用JWT进行跨域身份验证的单点登录流程

Single sign-on flow using JWT for cross domain authentication

网上有很多关于使用JWT(Json Web Token)进行身份验证的信息。但是,在多域环境中使用JWT令牌作为单点登录解决方案时,我仍然没有找到明确的解释。

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

使用OpenId Connect流程,我了解想要在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上进行身份验证!

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

因此,主要问题是:

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

应该 :

  • 用户是否会再次重定向到身份验证服务器?当用户对example1.com进行身份验证时,
    身份验证服务器可能已在用户上设置了cookie,因此example2.com的此新身份验证请求可以使用该cookie来查看用户已经过身份验证并立即将其重定向回
    example2.com使用相同的JWT令牌?
  • 或者,example2.com上的浏览器是否可以访问JWT令牌而无需再次访问身份验证服务器?我看到有跨存储解决方案,但是那些被广泛使用?它们是跨域SSO环境的建议解决方案吗?

我们不想要任何花哨的东西,我们会对最常用的解决方案感到满意!


应该再次将用户重定向到身份验证服务器并获取新令牌(JWT),该令牌专门针对example2.com。这就是OpenID Connect和任何其他跨域联合SSO协议的工作原理。


当用户未登录以请求凭据并发出新的身份验证令牌时,将用户重定向到中央身份验证服务是单点登录系统中使用oauth2或OpenIdConnect等众所周知的协议的常见方案

但是,当在跨域之间使用此架构时,主要缺点是每次由于同源策略导航到其他域时,用户将进行身份验证:会话令牌不能在域之间共享,因此SSO将会对待用户未经过身份验证。

example2.com无法访问example1.com的数据,但是有一个tecnique可以使用浏览器localStorage / cookies和指向中间域的iframe sso.example.com跨域共享数据

  • 要在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-域的消息传递与 - PostMessage的)

    为了简化开发,我们最近发布了一个带有JWT的跨域SSO,网址为https://github.com/Aralink/ssojwt

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


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

    所以
    example1.com
    example2.com

    会变得像

    example.com/example1

    example.com/example2

    (从用户方面来说,这通常更清洁)

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

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