为了实用性,您应该根据其对安全性和用户体验的影响来轮换密钥。这也取决于您的实现方式。
参与者包括:
- 客户端
- 资源提供者(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 Discovery的jwks_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,它有两个关键限制:
- 您无法跨集群节点进行扫描
- 无法使哈希元素过期
您可以按以下方式实现
- 创建包含公共JWK和私钥(存储为编码字节)的
njwk
元素的哈希对。
- 每个哈希对将基于某个时间块进行键控,比如一周中的某一天,假设
maxexp
不会超过maxjwke
。
- 每个哈希对将具有默认的
maxjwke
到期时间。
- 当密钥用于访问令牌时,它将仅扩展公钥的过期时间,使其为
maxjwke
+剩余访问令牌过期时间。(这一点确保了访问令牌在其访问期内有效。私钥仍然设置为过期。)
- 在提供JWKS列表时,应提供当前和上一个集合,只要它们没有过期。
- 在选择要签名的密钥时,应从未过期的当前桶中选择。