8

我想知道当主要浏览器默认禁用 3rd 方 cookie 时,如何在 2019 年处理 Oauth2 隐式授权流程中的刷新令牌。

一些细节:

当前设置:

  • UI SPA 应用下ui.example.com

  • 身份提供者(CloudFoundry 的 UAA)下uaa.api.example.com

设想:

  • 当用户登录时,身份提供者使用域的用户详细信息设置 cookie,uaa.api.example.com并在重定向的标头中返回 JWT Location

  • JWT 存储在本地存储中(for ui.example.com),但它的有效期仅为 1h,所以我想刷新它。

  • 通过发送到 IDP 授权端点的查询参数可以刷新prompt=none(过程在Auth0 指南中有很好的描述(它不是 UAA,但流程是相同的

  • 在每 20m 的隐藏 iframe 中创建 src 设置为uaa.api.exmaple.com/oauth/authorize?prompt=none的内容,无需用户提供凭据即可开始登录过程。当流程结束时,响应中返回的新 JWT 会再次存储在本地存储中。

问题:

  • 当允许第三方 cookie 时,浏览器会将 IDP 的 cookie 添加到 iframe 发出的请求中,因此流程可以正常工作,并且我会在响应中获得新的令牌。

  • 在浏览器设置中禁用第三方 Cookie 时,iframe 无法访问其自己的 Cookie,因此login_required会返回错误而不是新的 JWT。无法通过 iframe 访问 cookie 使令牌更新无法使用

问题:

我的 3rd 方 cookie 问题有什么解决方案吗?

如果没有,我可以使用隐式授予流程和 SPA 的替代方法来登录和刷新令牌吗?

4

4 回答 4

1

作为托管在不同域中的应用程序和身份服务器。这意味着您的应用程序正在执行跨域身份验证。跨域认证是通过第三方cookie实现的,禁用第三方cookie会导致跨域认证失败。

回答您的问题:

我的 3rd 方 cookie 问题有什么解决方案吗?

在同一个域下托管您的应用程序和身份服务器。在这种情况下,您可以使用子域。

如果没有,我可以使用隐式授予流程和 SPA 的替代方法来登录和刷新令牌吗?

解决方案:

我不熟悉 CloudFoundry。不确定他们是否支持。您可以通过在身份提供者端启用自定义域来解决此问题。因此,您的应用程序和身份提供者都将在同一个域中,并且 cookie 将被视为第一方。例如,将您的应用程序托管在https://acme.com并将您的身份提供者自定义域设置为https://login.acme.com

于 2019-02-24T00:19:27.437 回答
0

最后,我们决定采用不同的解决方案。当 JWT 生命周期结束时,我们会显示一个通知会话已超时的模式,并带有 2 个按钮,一个用于注销,一个用于保留会话。当用户点击“保持会话”时,将打开新的选项卡/弹出窗口,通过再次提供他的凭据或在 IDP 会话仍处于活动状态时自动提供用户在 IDP 中的重新身份验证。

所以流程是:

JWT lifetime ends-> 'keep session' in modal chose-> open new tab/popup-window with IDP login form-> successfully authenticated-> redirect back to app-> store token in browser's storage-> close popup-window/tab with window.close()->get new token from storage and use it in next calls

因为我们使用新的弹出窗口/标签来重新认证,所以第三方 cookie 没有问题。

这也带来了一个巨大的优势。用户无论何时返回应用程序都不会丢失他的工作,因为模态将在那里等待。我认为,另外它让我们满足了重新验证可访问性成功标准(AAA 级)

成功标准 2.2.5 重新认证

当经过身份验证的会话到期时,用户可以在重新进行身份验证后继续活动而不会丢失数据。

于 2019-03-21T10:45:41.120 回答
0

问题的根源在于iframe隐式授权类型的使用。

我认为您使用 iframe 的原因是跨域访问 cookie。现在,避免使用的最简单方法iframe是,将 cookie 的域设置为Domain=example.com并同时在example.com. 如果由于某种原因,您不能这样做,则需要采用以下方法。


推荐选项

隐式授权类型不安全。虽然这个问题不是关于授权类型的优缺点,但为了给我要解释的选项设置背景,让我简要列举一下我说隐式流不安全的原因:

  1. 缺少通过提供客户端密码和授权代码的客户端身份验证步骤。所以安全性较低
  2. 访问令牌作为 URL 片段发送回(以便令牌不会发送到服务器),该片段将继续保留在浏览器历史记录中
  3. 如果发生 XSS 攻击,恶意脚本可以很好地将令牌发送到远程服务器以控制攻击者

因此,推荐的选项是使用授权码授权类型。在 SPA(单页应用程序)中不使用授权码的原因之一是,它要求将客户端密码存储在浏览器中,我们知道浏览器无法保密。通过在服务器端使用代理组件(可以嵌入到资源服务器中)来保存客户端机密并充当 SPA 和授权服务器之间的代理,可以很容易地减轻这种风险。

这里(在授权代码授权类型中)流程如下所示:

  1. 用户点击 SPA 登陆页面上的登录按钮
  2. 用户被重定向到授权服务器登录页面。客户端 ID 在 URL 查询参数中提供
  3. 用户输入他/她的凭据并单击登录按钮。用户名和密码将使用 HTTP POST 发送到授权服务器。凭据应在请求正文或标头中发送,而不是在 URL 中(因为 URL 记录在浏览器历史记录和应用程序服务器中)。此外,应设置正确的缓存 HTTP 标头,以便不缓存凭据:Cache-Control: no-cache, no-store, Pragma: no-cache, Expires: 0

  4. 授权服务器根据用户数据库(例如 LDAP 服务器)对用户进行身份验证,其中用户名和用户密码的哈希(哈希算法,如 Argon2、PBKDF2、Bcrypt 或 Scrypt)与随机盐一起存储

  5. 成功验证后,授权服务器将根据 URL 查询参数中提供的客户端 ID 从其数据库中检索重定向 URL。重定向 URL 是资源服务器 URL
  6. 然后,用户将被重定向到资源服务器端点,并在 URL 查询参数中使用授权代码
  7. 然后,资源服务器将向授权服务器发出 HTTP POST 请求以获取访问令牌。授权码、客户端 ID、客户端密码应该放在请求正文中。(应使用上述适当的缓存标头)
  8. 授权服务器将在响应正文或标头中返回访问令牌和刷新令牌(使用上述适当的缓存标头)
  9. 资源服务器现在将通过设置具有域属性的适当 cookie 将用户(HTTP 响应代码 302)重定向到 SPA URL Domain=example.com(假设资源服务器和 UI 都在 的子域上example.com)。授权服务器的域无关紧要,因为它没有设置任何 cookie。

同样,可以将访问令牌刷新请求发送到代理组件,代理组件将从 cookie 中读取刷新和访问令牌,并使用提取的令牌、客户端 ID 和客户端密码调用授权服务器 api。

于 2019-02-27T16:41:52.523 回答
0

问题:

我的 3rd 方 cookie 问题有什么解决方案吗?

如果您在应用程序和 IDP 之间使用相同的顶级域,那么在禁用 3rd 方 cookie 时应该没有问题。 此链接还详细说明了使用成功的跨域策略。

如果没有,我可以使用隐式授予流程和 SPA 的替代方法来登录和刷新令牌吗?

我以前没有使用过 CloudFoundry,但大多数大型 OAuth2.0 提供商都提供公共客户端功能,其中公共客户端(例如您的 SPA)不需要客户端密码来获取访问/刷新令牌。这允许公共客户端使用授权代码授予,它可以允许通过刷新令牌刷新令牌,从而避免使用 HTTP 重定向和 cookie 的静默身份验证技术。

于 2019-02-25T12:17:57.013 回答