使用 JWT 进行跨域身份验证的单个 sign-on 流

Single sign-on flow using JWT for cross domain authentication

网上有很多关于使用 JWT (Json Web Token) 进行身份验证的信息。但是我仍然没有找到关于在多域环境.

中将 JWT 令牌用于 单个 sign-on 解决方案时的流程的明确解释。

我在一家公司工作,该公司在不同的主机上有很多站点。让我们使用 example1.comexample2.com。我们需要一个单一的 sign-on 解决方案,这意味着如果用户在 example1.com 上进行身份验证,我们希望他也能在 [=111 上进行身份验证=],自动.

使用 OpenId Connect 流程,我了解到想要在 example1.com 上进行身份验证的用户将首先被重定向到 身份验证服务器 (或 OP : "OpenId Provider")。用户在该服务器上进行身份验证,然后使用签名的 JWT 令牌将他重定向回原始 example1.com 站点。 (我知道还有另一个流程,其中 returns 一个 中间令牌 稍后可以将其本身交换为真正的 JWT 令牌,但我认为这对我们来说不是必需的)...

现在用户又回到了 example1.com 并通过了身份验证!他可以发出请求,在 Authentication header 中传递 JWT 令牌,服务器能够验证签名的 JWT,因此能够识别用户。不错!

第一题:

JWT 令牌应该如何存储在客户端?同样,有很多关于此的信息,人们似乎同意使用 Web Storage 是可行的方法,而不是旧的 cookies。我们希望 JWT 在浏览器重启之间保持不变,所以让我们使用 Local Storage,而不是 Session Storage...

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

此外,如果 example1.com 需要向我们的另一个域发出 Ajax 请求,我理解配置 CORS 将允许.但我们的主要用例不是 cross-domain 请求,它有一个 单一 sign-on 解决方案 !

所以题主:

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

应该:

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

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

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

在用户未登录时将用户重定向到中央身份验证服务以请求凭据并颁发新的身份验证令牌是使用众所周知的协议(如 oauth2 或 OpenId Connect)的单点登录系统中的常见情况

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

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

  1. example1.com中的用户进行鉴权,重定向到[=12=中的鉴权服务器],鉴权后下发JWT,存放在本域的localStorage中。在此之后,将用户重定向到原始域 example1.com

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

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

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

为了简化开发,我们最近在 https://github.com/Aralink/ssojwt

发布了一个带有 JWT 的 跨域 SSO

该方法完美兼容单点登录流程。这只是一种无需重定向即可共享身份验证令牌并在域联合时避免不必要的登录的方法

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

所以 example1.com example2.com

会变成

示例。com/example1

示例。com/example2

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

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

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