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


112

网络上有很多有关使用JWT(Json Web Token)进行身份验证的信息。但是我仍然没有清楚地说明在多域环境中将 JWT令牌用于单点登录解决方案时的流程。

我为一家在不同主机上有很多站点的公司工作。让我们使用example1.comexample2.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上进行身份验证!

另外,如果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环境的建议解决方案吗?

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

Answers:


28

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


15
但是由于它是SSO,因此用户不必重新发送身份验证凭据(例如,用户名/密码),对吗?那怎么办呢?身份验证服务器是否应该在第一次为用户设置标准cookie,以便当该用户从新域回来时可以自动对他进行身份验证?
2015年

7
但是,如果用户将浏览器配置为阻止所有cookie,该怎么办?
克里斯蒂安·韦斯特贝克

1
我猜应该对Cookie发出警告,“如果您的浏览器阻止Cookie,则该网站可能无法正常运行”
AnBisw

单点登录并不一定意味着用户正在通过cookie跟踪正在进行的会话:它的定义特征是,一个用户对同一个身份提供者重复使用相同的凭据即可访问不同的第三方应用程序,即不需要cookie,只是重复使用相同的信誉
Hans Z.

35

在未登录用户以请求凭据并发出新的身份验证令牌时,将用户重定向到中央身份验证服务是使用诸如oauth2或OpenId Connect之类的众所周知协议的Single Sign On系统中的常见情况。

但是,当跨域使用此架构时,主要缺点是由于同源策略,用户每次导航到其他域时将被重定向和认证:访问令牌不能在域之间共享(example2.com无法访问数据)的example1.com),所以目标域会将用户的未经认证,他重定向到中央SSO服务。

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

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

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

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

同源策略没有问题,因为sso.example.com如果源域和目标域能够相互识别,则可以访问其localStorage并允许iframe与父页面之间的通信(请参阅http://blog.teamtreehouse.com/cross-domain-带消息的消息传递

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

此方法与SSO流程完全兼容。这是在不进行重定向的情况下共享身份验证令牌并避免在域联合时不必要的登录的一种方法


3
除了此解决方案未遵循标准外,通常在跨域SSO中,一个跨管理边界,并且在这种情况下,对于两个域使用完全相同的JWT,将为一个域中的应用程序所有者冒充另一个域中的用户提供了可能性。域
Hans Z.

6
谢谢@HansZ。实际上,我们已经实现了该解决方案,以便对具有多个应用程序和相同用户的多个域进行一次管理。该操作类似于google系统(相对而言)
pedrofb

2

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

所以example1.com example2.com

会变成像

example.com/example1

example.com/example2

(从用户的角度来看,这通常更清洁)

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

如果不是这样,您可能不得不求助于username + pin,因为浏览器对跨域交互的要求越来越严格。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.