【问题标题】:How practical would this JWT Implementation be?这个 JWT 实现有多实用?
【发布时间】:2017-07-11 13:50:44
【问题描述】:

免责声明,我是 JWT 的新手,所以如果其中任何一个完全没有意义,你现在知道为什么大声笑了。

动机 这个实现试图解决的安全问题可以用这个场景来概括:

合法用户使用公共计算机登录网站并忘记退出,攻击者坐在那台计算机上,复制粘贴令牌并在他回家后随时使用它,(因为它总是有效的直到秘密发生变化,或者如果您将令牌存储在数据库中,直到用户更改某些有效负载信息[如果用户从不更新信息怎么办],那么令牌将永远有效)。

对上述问题进行排序的身份验证流程

1.   Client logs in
      1.1  Verify login details, and if valid:
      1.2  Create token using user id, global secret and expiry date
      1.3  Store token in Database
      1.4  Send token to client
2.   Client stores token [your choice where u wanna store it]
3.   When client sends a request to an authenticated route, use authentication middleware to do the following checks
      3.1  Verify token hasn’t been tampered with
      3.1.1  If not tampered, go to 3.2
      3.1.2  If tampered, redirect to /login
      3.2  check if expiration date is less than current date
      3.2.1  if not less, let user through to the requested route, by calling next()
      3.2.2  if less, check in database if expired token matches the token stored in database
        (to verify if it’s the latest expired token, or not)
        3.2.2.1 if doesn’t match, redirect to /login
        3.2.2.2 If matches
            3.2.2.2.1 create token with renewed expiration date
            3.2.2.2.2 store token in database
            3.2.2.2.3 send token to client

上述实现的安全缺陷 如果攻击者可以访问令牌,并且是在令牌过期后发出第一个请求以获取新令牌的攻击者,那么当合法用户尝试获取新令牌并将其注销时,这将使合法用户无效因为他们的令牌与存储在数据库中的令牌不匹配。现在只有攻击者拥有与数据库中存储的相同的令牌。

缓解这种情况的方法 通过登录或注销无效:在登录时生成新令牌/在注销时删除令牌,覆盖数据库中的旧令牌,这将使所有先前发布的令牌在过期后立即失效。即下次攻击者尝试在过期时获取新令牌时,它不会匹配数据库中的一个,因此他们将永远被拒绝使用该令牌。

可用性问题 登录或注销会使所有其他设备上的令牌失效,因此您必须在这些设备上重新登录。

可能的解决方法 对设备类型进行简单的请求标头检查,并在登录和注销时为每个设备存储不同的令牌。然后在需要刷新令牌时根据不同设备的if语句进行不同的数据库查询,因此您知道要刷新哪个。

【问题讨论】:

  • 详细场景! +1

标签: security authentication jwt


【解决方案1】:

1.3 在数据库中存储令牌

没有必要也不推荐。验证 JWT 的签名是 JWT 有效的证明。保存令牌需要在每个请求中进行不必要的存储空间和数据库访问

合法用户使用公共计算机登录网站,然后忘记注销,攻击者坐在那台计算机前,复制粘贴令牌并在他回家后随时使用。

这个安全问题是可能的,但考虑到攻击风险很低,受影响的用户数量不会很高,因为它需要在使用您的网站后对共享计算机进行物理访问。预防和缓解措施应与问题的严重性相称。

您已提议在真实用户新登录/注销时使旧令牌失效,但该用户没有注销,因此无法降低风险。服务器不知道是否令牌来自真实用户或攻击者。拥有 JWT 是身份验证的证明。

我建议采取以下预防措施:

  • 到期时间短:每 3-5 分钟更新一次令牌

  • 使用 会话存储 代替 cookie/localStorage:浏览器关闭时会清除会话存储。

如果这些操作对您来说还不够,请考虑请求登录凭据,而不是存储 JWT。

您的其余观点基于将 JWT 存储在数据库中。正如我在上面评论的那样,使用 JWT 没有意义

可用性问题登录或注销会使所有其他设备上的令牌失效,因此您必须在这些设备上重新登录。

为每台设备颁发一个新令牌。建议让令牌过期,但如果您需要使令牌失效,您可以在 JWT 中使用包含唯一标识符 jti 的黑名单。

【讨论】:

  • 而不是应该说的登录/注销,登录通过使所有先前发布的令牌无效来降低风险,因为它们不能再用于获取新的令牌。会话存储对用户不友好,因为这意味着用户必须重新登录。您能否详细说明一下到期时间有多短会阻止建议的情况?如果攻击者可以访问最新的令牌,他们的令牌无论如何都会永远刷新,直到真正的用户登录并使其无效,或者如果全局密码发生变化?感谢您花时间解释它。
  • 在新登录后使旧令牌失效意味着攻击者将无法继续使用被盗令牌。减轻问题,但不避免它。并且具有您的系统一次只能在一台设备上使用的副作用。或者,您可以将设备标识符或 IP 添加到令牌中,但也有其自身的缺点
  • 较短的到期时间通过减少暴露时间来防止(但不能避免)令牌被盗。概率较低,因为攻击者只有几秒钟的时间进入共享计算机,复制和粘贴。我同意会话存储对用户不友好。重视安全措施的风险/收益,因为您永远不会获得 100% 安全的系统
  • 为什么攻击者只有几秒钟的时间进入共享计算机?就算token过期很久了,只要真实账户所有者不重新登录,应用程序不就是给攻击者发送一个新的token吗?在我看来,攻击者的利用窗口似乎仅受合法用户重新登录所需的时间限制?
  • 服务器在令牌中设置过期时间(exp 声明)。例如 2 分钟,App 使用旧令牌每 1:45 自动更新令牌。 在 exp 时间之后,服务器将拒绝任何请求。所以攻击者只有 2' 来窃取令牌。假设用户必须关闭浏览器、机器等,实际窗口更小
【解决方案2】:

我认为它看起来还不错,尽管 pedrofb commensta 是有效的。但是,请考虑不将 JWT 本身存储在数据库中的选项,而是使用刷新令牌。刷新令牌不是 JWT,它只是一个随机数、时间戳或类似的,刷新令牌嵌入在 JWT 中。

还可以考虑在 JWT 上添加软到期。软到期是您的专有到期。只要未超过标准到期日期,JWT 就有效,但在软到期后,您希望将 JWT 中的刷新令牌验证为您存储在数据库中的时间。这将是实际验证用户到数据库的频率的心跳。另一方面,标准到期日期是用户需要与您的 BE 至少交互一次以发布新的 JWT(具有新的到期日期)的日期。因此,到期日期可能是 3 个月,5 分钟后软到期。

如果用户注销,如果您检测到奇怪的行为,则更改 PW och,您可以使数据库中的刷新令牌无效。您还可以在每次出现新 JWT 时更改刷新令牌,以防止旧 JWT 被更新。此外,您可以为用户登录的每个设备存储一个单独的刷新令牌,就像您为原始提案计划的那样。 (这允许用户从单个设备注销,监控用户从哪个设备登录并远程从设备注销。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-08
    • 2017-07-25
    • 2017-03-09
    • 1970-01-01
    • 2021-08-10
    • 2019-07-11
    • 2018-11-27
    相关资源
    最近更新 更多