我正在尝试使用Keycloak OAUTH服务器(7.0.11),它看起来运行得很好,但是我仍然对如何验证它生成的令牌感到困惑。例如,我生成了一个id_token
并将其粘贴到http://jwt.io中,它显示了一个格式良好的有效负载和以下头部:
{
"alg": "RS256",
"typ": "JWT",
"kid": "<my-key-id>"
}
它还显示“Signature Verified”,并以某种方式将有效的RSASHA 256公钥检索到jwt.io页面中的相应表单中。
我希望自己能够通过检查签名来验证令牌。我的理解是,我通过从keycloak服务器JWKS Certificate-Endpoint检索公共签名密钥来实现这一点:生成的对象包含一个密钥:
{
"kid":"<matches-my-key-id-above>",
"kty":"RSA",
"alg":"RS256",
"use":"sig",
...
"x5c":["<snip>"],
...
}
很好,kid
匹配,但是x5c
中的值 * 不 * 匹配http://jwt.io显示的公钥,当我粘贴我的x5c
值到它的位置时,表单说签名无效。根据https://www.rfc-editor.org/rfc/rfc7517,值应该已经是base64编码的(看起来我也是)。
不幸的是,我不能把范围缩小到一个很有针对性的问题。但是...
- 为什么我的keycloak身份验证服务器没有报告验证令牌的密钥--特别是因为令牌中的
kid
与唯一的JWKS密钥匹配? - 如果我的头文件不包含任何
jku
来查询,http://jwt.io如何找到任何公钥来检查签名?
TIA各位。
4条答案
按热度按时间hsgswve41#
我发现了一个有趣的解释--但还不完全是答案--在Keycloak服务器领域服务器设置中,有一个公共密钥和一个证书。
公钥确实是验证我的访问令牌的正确值,以及jwt.io当我加载我的访问令牌时在www.example.com表单中显示的内容(仍然不知道它是如何检索的)。
证书是当我向证书端点/JWKS发出HTTP请求时返回的内容。
所以我不应该通过证书来验证我的访问令牌吗?或者有没有另一组参数可以用来通过证书而不是公钥来验证?
kmb7vmvb2#
已解决:不久前已解决此问题,但忘记更新此主题:技巧是查询主发布者领域:
https://<server>:<port>/auth/realms/<realm>
,它 * 确实 * 返回域公钥:该公钥对所有令牌进行签名,而不是对领域JWKS端点返回的x509证书进行签名。
knpiaxh13#
我有一个描述这个过程的blog post,除了在将键粘贴到jwt.io之前用众所周知的分隔符(如下面这样的分隔符)将键括起来之外,您所做的一切听起来都是正确的。
当然,programmatic solutions使用的库可以自动执行这类操作。
Keycloak的密钥详细信息可能会略有不同,例如:
a8jjtwal4#
jwt.io如何知道您的公钥的答案是,当您将公钥粘贴到jwt.io中时,在该页面上运行的javascript会获取并使用JWT中的iss字段:
现在,由于您可能正在端口8080上运行本地keycloak,因此该页将在本地触发对以下URL的调用:
这些调用返回一个密钥数组,jwt.io中的页面处理这些数组,它根据jwt中定义的kid提取正确的密钥,并将该密钥的整个json部分放入解码页面的公钥部分。这就是它“知道”你的公钥的方式。
您可以尝试关闭您的本地keycloak服务器,将您的jwt粘贴到jwt.io中,然后意识到您的验证将失败。