JWK何时过期?JWKS轮换策略。

18

我正在阅读关于JWKS的内容,并找到了有关密钥轮换概念的信息 - https://developer.okta.com/docs/concepts/key-rotation/

假设我在我的应用程序中使用了JWKS,但我没有定期获取它们,所以只是硬编码。单个密钥JSON对象如下:

{
      "kty": "RSA",
      "e": "xxx",
      "use": "sig",
      "kid": "xxx",
      "x5t": "xx",
      "x5c": [
        "xxx"
      ],
      "n": "xxx

}

JWKS提供了公钥,以便您可以验证JWT。

  1. 是否可以获取JWKS的过期信息?例如,我能否使用JWK生成.cert文件并打开它以检查过期日期?
  2. 答:不可能从JWKS中获取过期信息。
  3. JWKS提供者是否在规划密钥轮换时暴露信息,或者这是敏感信息?
  4. 答:JWKS提供者可能会通知密钥轮换的计划,但是这取决于服务提供商是否愿意披露此类信息。

请考虑上述示例,因此我在应用程序中有键,并想知道何时应该替换它们。

当然,我知道这是不好的实践(我应该直接从JWKS端点获取密钥并保持安全),但这只是一个示例(如果这是愚蠢的示例,请提出更好的示例来描述上下文)。

2个回答

33
  1. JSON Web Key Set(JWKS,也称为JWK集合)是一个JSON Web Key(JWK)列表。由于JWK集合仅是一个容器,因此它不包含任何元数据,如到期日期/时间。

  2. 它之所以不暴露这一信息,至少有两个原因:

  • RFC 7517 是规定JWK和JWK Set行为的规范。它没有提及或要求提供者发布到期日期/时间。这可能是由于原因#2:
  • 提供者应能够随时出于任何原因删除密钥。可能的原因:密钥已经被破坏。(对于私钥/公钥对,这意味着私钥已经被泄漏,相应的公钥通过JWKS发布的应该被从流通中移除)。这个例子是一个异常情况,但确实会发生,并且提供者必须立即采取措施解决它。

尽管存在紧急情况,但提供者通常会定期轮换密钥以维护良好的安全卫生习惯。为了处理密钥轮换(无论是计划的还是紧急情况),您的应用程序应遵循简单的算法。它应定期从JWKS端点获取密钥,构建所有密钥的本地副本,并根据上次获取的时间添加/删除此副本中的密钥。您的应用程序只应使用在本地副本中找到的密钥来执行加密操作,例如验证JWT上的签名。

每个JWK都有一个kid(密钥ID)参数,这个参数用于匹配特定的密钥。RFC 7517建议在密钥更换期间使用kid来在JWK集合中选择一组密钥。当您的应用从JWKS获取密钥时,您将比较来自JWKs的密钥集与本地副本中的密钥集。比较是基于kid进行的。如果某个kid的密钥存在于JWKS中但不存在于本地副本中,则应将该密钥添加到本地副本中。反之,如果某个kid的密钥存在于本地副本中但不存在于JWKS中,则应从本地副本中删除该密钥。 您的应用程序需要多频繁地从JWKS获取密钥?这取决于您的应用程序和/或组织的风险容忍度。有些应用程序每分钟获取一次,有些应用程序每小时或每天获取一次。 假设您的应用程序从未进行此获取操作,密钥已经硬编码在您的应用程序中。这将有效,直到提供者删除该密钥。 (我们假设这里谈论的是公钥。一个JWK可以代表私钥...而且您不想将其嵌入到您的应用程序中)。一些提供者不会轮换密钥,或者只会很长一段时间才这样做。如果您正在处理一个您熟知的提供者,并且他们向您保证不会轮换密钥,则将密钥嵌入到您的应用程序中的风险较低。

通常将公钥嵌入应用程序并不是一个好主意。如果您将使用JWKS端点,请按照上述说明实施简单的获取和更新解决方案。


2
谢谢您提供这么详细的答案!我真的很高兴有人能补充一些关于密钥轮换的内容。 - maxi175

-1
为了实用性,您应该根据其对安全性和用户体验的影响来轮换密钥。这也取决于您的实现方式。
参与者包括:
- 客户端 - 资源提供者(RP) - 身份提供者(IP)实现细节...没有理由IP和RP不能是同一实体,这就是OIDC出现之前的情况。但是,考虑到扩展或使用其他OIDC提供者,以这些术语思考仍然是有益的。
假设您的实现是将访问令牌作为JWT声明的Json Web Signature(JWS)内容。访问令牌中的JWT方法主要替换了JSESSIONID的概念,以及在后端存储此类信息并将存储责任转移给客户端。
从客户端的角度来看:
1. 如果客户端没有OAuth令牌,则执行某些过程(例如OIDC)以获取OAuth令牌。 2. 如果客户端具有OAuth令牌,则将access_token作为承载者发送到RP。 3. 如果RP响应401或客户端认为RP将响应401。 - 客户端将使用刷新令牌端点从IP获取新令牌。 - 如果IP响应错误,则刷新过程失败并注销用户。 - 否则继续。 4. 否则只是标准RP响应。
第三步指定了刷新令牌过程。这需要注意,因为在确定轮换策略时也需要考虑这一点。

根据引用部分的情景,只有一个方需要真正关心签名,那就是为了识别用户和授权级别数据而消耗JWT的一方,即RP。

承载令牌中的JWT将与特定的JWS相关联,并且可以重复使用直到时间过期。由于这经常发生,因此RP需要具有一些快速进行验证的层。它通过拥有由IP提供的签名者的公钥来实现这一点。在OpenID Connect(OIDC)标准中,它由OpenID Discoveryjwks_uri引用。无论RP如何检索它,RP必须有一种可信赖的方式从IP获取密钥

现在让我们加入一些变量

  • exp 访问令牌过期时间,而不是持续时间
  • jwke JSON Web 密钥过期时间,而不是持续时间
  • njwk 活动 JWK 数量
  • maxjwke JSON Web 密钥过期持续时间
  • maxexp 访问 Web 密钥过期持续时间

假设 jwke >= exp,否则客户端将意外地收到 401 错误,因为密钥对于其访问令牌无效。

现在,为了简单起见,您可以为每个访问令牌设置一个 JWK,这样可以工作,并且相对安全,但会消耗后端资源,因为它一直在创建加密令牌。但这是最低要求。

因此,至少我会有一组合理的 JWK 作为池,可以是 10 个,也可以是 100 个,这取决于您的容忍度。

那么最大值是多少?嗯,这取决于您的容忍度和创建令牌的成本。

但是,无论您的容忍值如何,您需要确保对于给定的JWK,在访问时间之前它不会过期。

IP实现注意事项

现在假设您正在实现REDIS,它有两个关键限制:

  1. 您无法跨集群节点进行扫描
  2. 无法使哈希元素过期

您可以按以下方式实现

  • 创建包含公共JWK和私钥(存储为编码字节)的njwk元素的哈希对。
  • 每个哈希对将基于某个时间块进行键控,比如一周中的某一天,假设maxexp不会超过maxjwke
  • 每个哈希对将具有默认的maxjwke到期时间。
  • 当密钥用于访问令牌时,它将仅扩展公钥的过期时间,使其为maxjwke+剩余访问令牌过期时间。(这一点确保了访问令牌在其访问期内有效。私钥仍然设置为过期。)
  • 在提供JWKS列表时,应提供当前和上一个集合,只要它们没有过期。
  • 在选择要签名的密钥时,应从未过期的当前桶中选择。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接