首页 > 解决方案 > 在集群身份验证服务中存储 RSA 密钥

问题描述

我想构建一个使用 JWT 和使用 RS256 生成的签名的身份验证服务。在单服务器解决方案中,实现相当简单。但是,当涉及到使其成为多节点时,有两个相关的问题我没有找到明确的答案:

  1. 在集群解决方案中,每个服务器应该使用自己的密钥对还是多个节点可以使用共享密钥对?在那种情况下,如何有效地构建一个不包含太多键的 JWK?

  2. 另一方面,如果在不引起重大安全问题的情况下共享私钥是可能的,那么共享密钥和管理其轮换的最佳方法是什么?

标签: authenticationjwtrsacluster-computinghmac

解决方案


如果可能(IMO),您应该使用单个私钥来签署访问令牌。

拥有多个只会增加复杂性(例如,后端资源服务器需要逻辑来计算出用于 JWT 验证的公钥,或者循环通过多个公钥来验证 JWT)而且我并没有真正看到任何安全优势.

FWIW 可能存在需要在后端支持多个密钥的业务原因,例如,如果您的公司有多个具有单独身份验证租户/登录域的产品,您可能需要在共享后端服务/功能中支持多个密钥 - 对于在这种情况下,您需要使用诸如令牌颁发者 ( iss) 声明之类的东西来确定用于 JWT 验证的公钥。

WRT旋转键;如果您使用的是像 Auth0 这样的 PaaS IDP,它可能已经为您处理好了。如果您使用像 Keycloak 这样的 COTS 产品(或者如果您已经推出了自己的 IDP),则需要在 JWKS 端点中定义多个公钥(尽管是临时的)。新密钥将被指定为“活动”,并将用于签署所有后续令牌,而旧密钥将被指定为“被动”,仅需要验证在轮换之前发布且尚未发布的访问令牌已到期。注意:一旦使用旧密钥签名的所有访问令牌都过期,您可能可以停用/删除旧密钥。

这是关于可能有用的旋转密钥的 Keycloak 文档的链接。

在您进行 JWT 验证的后端服务中,kid应缓存与 JWT 上的密钥 ID ( ) 声明对应的公钥。如果使用新私钥对请求进行签名,则 JWT 应该具有不同的密钥 ID。如果后端服务遇到新的密钥 ID,它应该懒惰地返回 JWKS 端点以获取与新密钥 ID 关联的公钥(然后这也应该被缓存)。

在最常见的编程语言中,有一些库可以为您处理大部分内容,例如,我使用 Microsoft.AspNetCore.Authentication 包在 .NET Core 中完成了 JWT 验证,我需要做的就是配置一个 Open ID matadata 端点(其中引用JWKS 端点)以及诸如密钥轮换和缓存之类的事情都是透明地处理的。


推荐阅读