我需要从Microsoft Graph API验证令牌的签名。我了解所使用的签名密钥的指纹位于JWT的标头中:
并且它对应于您可以从知名端点获得的键:
https://login.microsoftonline.com/[TENANT-ID]/discovery/v2.0/keys
我的计划是将密钥列表存储在缓存中,以便在需要进行验证时可以为令牌查找正确的签名密钥。但是我知道有时按键可能会旋转。
由于没有太多文档,所以我的问题分为多个部分:
这是一个合理的策略吗?
新密钥是否在众所周知的端点处追加到列表中?我假设这个列表随着时间的推移而增长,所以如果令牌需要它,我总是可以得到一个较旧的密钥吗?除了刷新我的缓存外,还需要使用可用的密钥对其进行补水。
较早的键在什么时候从列表中消失?我假设必须有时间或计数截止。
似乎最新的键是第一个记录,并以降序排序?
为什么x5c是数组?每个记录不应该只有一个签名密钥吗?我假设我应该只使用.x5c [0],但是在什么情况下这里会有多个项目?
Key rollover已在各种库中为您实现;明智的策略是使用其中之一而不是自己动手。
https://login.microsoftonline.com/[TENANT-ID]/discovery/v2.0/keys
中的JSON文档符合JSON Web密钥(JWK)规范(RFC 7517)。规范不规定keys
数组中键的顺序:
"keys"
参数的值是JWK值的数组。通过默认情况下,数组中JWK值的顺序并不表示尽管JWK集的应用,但是它们之间的优先顺序可以选择为其目的分配含义,如果所需。
Microsoft对密钥过渡的实现似乎将新密钥添加到列表的顶部。没有对此的书面保证,我们不建议您依赖它。至于密钥是否从列表中删除,同样也没有发布的规范。如果证书被吊销或过期,则不能用来验证签名。常识要求应在该时间点将其从列表中删除。微软的key rollover doc指出
在紧急情况下,[键]可能会立即翻转。
翻译:您应该多久返回一次已发布的https://login.microsoftonline.com/[TENANT-ID]/discovery/v2.0/keys
上的“主”键列表,取决于无法在您的应用中验证令牌的重要性/后果。
x5c
是一个数组,因为它代表certificate chain。 Microsoft的实现使用的是单个证书(链的长度= 1),但没有什么可以阻止它们在将来的某个时间点使用更长的链。实际上,他们不太可能这样做,因为这会影响许多不合格的应用程序以及它们自己的库。