稍后让我来回答您的问题,并从实际讨论刷新令牌的全部目的开始。
所以情况是:
用户打开应用程序并提供他的登录凭据。现在,该应用程序很可能正在与 REST 后端服务进行交互。REST 是无状态的,无法授权访问 API。因此,到目前为止,在讨论中,无法检查授权用户是否正在访问 API,或者只是一些随机请求通过。
现在为了能够解决这个问题,我们需要一种方法来知道请求来自授权用户。所以,我们所做的是引入一种叫做访问令牌的东西。所以现在一旦用户成功通过身份验证,他就会获得一个访问令牌。这个令牌应该是一个长且高度随机的令牌(以确保它不会被猜到)。这就是 JWT 发挥作用的地方。现在您可能/可能不想在 JWT 令牌中存储任何用户特定的详细信息。理想情况下,您只想在 JWT 中存储非常简单、极其不敏感的细节。JWT(正在使用的库)本身负责操作 JWT 哈希以检索其他用户的详细信息(IDOR 等)。
所以,现在,我们的授权访问问题已经解决了。
现在我们讨论一个攻击场景。假设使用上述所有用户 Alice,使用该应用程序,拥有授权访问令牌,现在她的应用程序可以向所有 API 发出请求并根据她的授权检索数据。
假设Alice以某种方式丢失了访问令牌,或者换句话说,对手 Bob 获得了对 Alice 的访问令牌的访问权。现在,尽管 Bob 未经授权,但可以向 Alice 授权的所有 API 发出请求。
我们理想中不想要的东西。
现在这个问题的解决方案是:
- 要么检测到有这种事情发生。
- 减少攻击窗口本身。
仅使用访问令牌,很难实现上述条件 1,因为无论是 Alice 还是 Bob,都使用相同的授权令牌,因此来自两个用户的请求是不可区分的。
因此,我们尝试实现上述 2,因此我们为访问令牌的有效性添加了一个过期时间,例如访问令牌在“t”(短期)时间内有效。
它有什么帮助?好吧,即使 Bob 拥有访问令牌,他也只能在它有效时使用它。一旦过期,他将不得不再次取回它。现在,当然,你可以说他可以像第一次一样得到它。但话又说回来,没有什么比 100% 安全!
上述方法仍然存在问题,并且在某些情况下是不可接受的。当访问令牌过期时,它将要求用户输入他的登录凭据并再次获得授权的访问令牌,至少在移动应用程序的情况下,这是一种糟糕的(不可接受的)用户体验。
解决方案:这就是刷新令牌的用武之地。它也是一个随机的不可预测的令牌,它也首先与访问令牌一起发布给应用程序。这个刷新令牌是一个非常长寿命的特殊令牌,它确保一旦访问令牌过期,它就会向服务器请求新的访问令牌,从而无需用户重新输入他的登录凭据来检索一个新的授权访问令牌,一旦现有的已过期。
现在您可能会问,Bob 也可以访问刷新令牌,类似于他破坏访问令牌的方式。是的。他可以。然而,现在很容易识别这种事件,这在仅使用访问令牌的情况下是不可能的,并采取必要的措施来减少造成的损害。
如何?
对于每个经过身份验证的用户(通常在移动应用程序的情况下),都会向应用程序颁发一对一映射的刷新令牌和访问令牌对。因此,在任何给定时间点,对于单个经过身份验证的用户,只有一个访问令牌对应于刷新令牌。现在假设如果 Bob 泄露了刷新令牌,他将使用它来生成访问令牌(因为访问令牌是唯一被授权通过 API 访问资源的东西)。一旦 Bob(攻击者)请求使用新生成的访问令牌,因为 Alice(真正的用户)的访问令牌仍然有效,服务器就会将此视为异常,因为对于单个刷新令牌,在一次。识别异常,服务器将销毁有问题的刷新令牌以及所有这些,它的关联访问令牌也将失效。从而防止对任何需要资源的授权的任何进一步访问,无论是真实的还是恶意的。用户 Alice 将被要求再次使用她的凭据进行身份验证并获取一对有效的刷新和访问令牌。
当然,您仍然可以争辩说 Bob 可以再次获得对刷新和访问令牌的访问权并重复上面的整个故事,这可能会导致对真正的真正客户 Alice 的 DoS,但是再一次没有什么比 100% 安全.
同样作为一种好的做法,刷新令牌应该有一个到期时间,虽然很长。