【问题标题】:Best Practices for Securing a SPA with JWTs使用 JWT 保护 SPA 的最佳实践
【发布时间】:2020-01-16 13:15:16
【问题描述】:

背景

很抱歉这个问题有点开放,但我只是想了解它是如何工作的,而且我是这个领域的新手。

我正在构建一个由 (Apollo) 服务器支持的 SPA。这个问题与使用 JWT Bearer 令牌的传统身份验证有关。我会假设服务器有一个有效的 TLS 证书。

问题

我会先写我理解的,如果我有任何错误,请纠正我。干杯!

用户注册。我们向 SPA 发送带有一些元数据(例如 exp)的访问令牌,并将其存储在 httpOnly(以防止 XSS)、SameSite=strict(以防止 CSRF)、secure(以防止 MITM 攻击)cookie 中。然后,它会随每个身份验证请求一起发送,而无需查询数据库,如果我们将角色/范围附加到 JWT 有效负载,即使是授权也无需查询用户数据库。

第一个问题出现在用户尝试注销时。

问题 1

使用 httpOnly cookie 注销用户的最佳做法是什么? Here 我读到最佳实践是设置两个 cookie,一个没有httpOnly(我猜是相同的内容(JWT)?)并且在服务器身份验证逻辑中都需要。当用户注销时,我们会删除非 httpOnly 的,这会有效地注销用户。

问题 2

如何处理多设备登录?我猜 JWT 没有任何东西来识别设备,所以只需在 cookie 中发出一个新令牌。

到目前为止一切顺利。

现在,假设上述令牌永远不会泄漏,我相信这是一个安全的系统。然而,实际上事情并没有那么简单。有人可以从无人看管的计算机上快速复制 cookie 数据。这甚至可以使用 U 盘脚本来完成,因为 cookie 只是文件系统中的文件。

问题 3

有什么方法可以缓解这种情况?这里还有一些问题,以及我的扶手椅解决方案:)

3.1:浏览器是否有 API 可以安全地加密 cookie?如果是这样,我们可以加密 cookie。我猜他们没有。

3.2:我的整个想法是使用子网掩码和 IP 地址来唯一标识设备。但这可能行不通-我假设子网掩码没有像IP地址这样的http请求中携带,并且在js中执行此操作将受攻击者的支配。最后,这对(IP,子网掩码)不是一个很好的设备标识符,因为在断开连接后,另一个设备可以使用该子网掩码。去他妈的。

3.3:使用短期 JWT。 imo有点hacky解决方案。我们将 JWT exp 设置为 15-30 分钟,并假设在那段时间内,攻击者 can't cause much damage。删除帐户等关键操作仍然需要密码(将通过 https 发送),从而限制了攻击的范围。 15 分钟后,系统将提示用户重新登录并可以恢复所有效果或联系支持人员将其删除。

但是,出现了一个新问题:我们不希望用户必须每 15 分钟登录一次。我的理解到此结束:

3.3.1:使用存储为 cookie 的长期刷新令牌 - 实际上并没有太大变化。

3.3.2:在数据库中使用长期刷新令牌。好吧,看起来很公平。一旦用户在其帐户中发现恶意行为,他们就可以联系支持人员,所有刷新令牌都将被删除,攻击者的剩余时间将少于 15 分钟。实际上,我们只是对是否存在违规感兴趣,所以我们可以使用布尔值;为什么要使用刷新令牌?

恕我直言,问题是攻击者仍然永远可以访问视图。所以我们仍然需要将它与一些设备标识(用户代理、IP 地址...)结合起来,从而引入额外的复杂性。

对于非关键(银行)应用程序来说,似乎最好的解决方案就是使用长寿命访问令牌。我将尝试用两个论点来证明该决定的合理性:

3.3.3:如果有人可以物理访问您的设备,他们通常会做比复制 cookie 更糟糕的事情。

3.3.4:Facebook 似乎使用 6 个月的访问令牌?至少表面上看起来是这样的:我去了 fb.com,删除了我的 c_user cookie,cmd+r,登录,并在 6 个月内创建了一个新的,减去一些更改。但我无法以有效的方式将 cookie 从 Brave 复制到 Chrome。我做错了什么还是有防止此类攻击的实际好方法(无需在每个请求上查询数据库)?

结束

很抱歉,文本很长,但是关于安全性的问题太多且不完整,我只想确保我做的一切都是正确的。如果有人对我写的内容有 cmet 或部分答案,我将非常感激。我很高兴了解这个新的网络安全领域!

【问题讨论】:

    标签: security cookies jwt


    【解决方案1】:

    这个问题有点太笼统了,但让我试着回答几点。

      1234563您可以向服务器发出请求,并要求它为您删除 cookie。另见下文。
    1. 当然,来自不同设备的同一个用户只是另一个 JWT。

    2. 这种威胁并非特定于 JWT,一个普通的旧会话 ID 可能会以同样的方式被盗。加密它没有帮助,因为加密版本会被盗,而这就是身份验证所需的全部内容。此外,无论从哪里窃取令牌,密钥都必须可用。您大多不必处理这个问题,客户端的物理安全性通常超出了典型 Web 应用程序的范围。您可以而且应该做的是使用长期刷新令牌发出短期访问令牌,并以不同方式存储它们

    对于许多用例来说,这是一种相当安全的方法:

    • 如果一个普通的旧会话 id(~一个大的随机数)就足够了,不要使用有意义的令牌(信息超出一个大的随机数)。经常这样。
    • 使用不同的来源进行身份验证(颁发令牌)和服务(使用令牌进行身份验证)。 OpenID Connect(以及某种程度上的 Oauth2)具有身份提供者和服务提供者的这些概念。
    • 访问令牌可以存储在服务源的本地存储中,允许您的 javascript 访问身份信息和声明,并接受潜在 XSS 访问的风险。并非所有应用程序都是这种情况,因此您必须评估此风险!此外,将令牌存储在 cookie 中会使应用程序容易受到 CSRF 的攻击,而 SameSite 只能在最新的浏览器(大约在过去一年发布)中工作,这可能还不够。这是否再次成为您的问题取决于您的用例和威胁模型。
    • 刷新令牌可以存储在一个httpOnly cookie 身份提供者来源。因此,如果旧的访问令牌不再工作,您必须在应用程序中实施适当的错误处理,以尝试从身份提供者获取新的访问令牌。
    • 所有这些都应该在一个知名且经过充分测试的库中实现,因为要做到这一点并不容易。您可以而且应该使用多种出色的身份识别解决方案(付费和免费)。

    【讨论】:

    • 酷,非常感谢!将通过建议
    猜你喜欢
    • 2018-11-02
    • 2017-11-16
    • 2017-07-12
    • 2011-06-27
    • 2020-09-21
    • 2016-10-20
    • 1970-01-01
    • 2018-04-28
    • 2017-06-07
    相关资源
    最近更新 更多