jwt - 如何获取 ADFS 公钥并验证 JWT 令牌上的签名?
问题描述
我需要验证在 ADFS 服务器上签名的 JWT 令牌的签名。我可以验证自签名 JWT 令牌,但不能验证从 ADFS 收到的令牌。我应该如何获取公钥?
为了从 ADFS 服务器获取公钥,我让我的同事从 ADFS 服务器导出证书。在 ADFS 控制台上,他查看了“服务”>“编辑联合服务属性”、“常规”选项卡,在那里他找到了三个整体。它们位于“令牌签名”、“令牌解密”和“服务通信”标题下。对于每个人,他都查看了证书,然后导出了 DER 证书(没有私钥)。然后将它们转换为 PEM(使用
openssl x509 -inform der -in cert.cer -out cert.pem
),但这些密钥都不允许我的代码验证嗅探到的 JWT 令牌。
我的 Java 代码采用 JWT 令牌和公钥,并验证令牌是否使用公钥签名。如果我使用自签名密钥对和自生成 JWT 令牌,则代码似乎可以工作,并报告签名正常。当令牌从来自 ADFS 的消息中的 HTTP 标头复制时,相同的代码会报告签名无效。
这是我用来加载 PEM 公钥的代码:
FileInputStream fis = new FileInputStream(publicKeyFile)
Reader keyReader = new InputStreamReader(publicKeyStream);
PemReader pemReader = new PemReader(keyReader);
PEMParser pemParser = new PEMParser(pemReader);
Object pemObject = pemParser.readObject();
if (pemObject instanceof X509CertificateHolder) {
X509CertificateHolder x509CertificateHolder = (X509CertificateHolder) pemObject;
X509Certificate x509Certificate = new JcaX509CertificateConverter()
.setProvider("BC").getCertificate(x509CertificateHolder);
return x509Certificate.getPublicKey();
}
这是我用来验证签名的代码:
String signatureAlgorithm = publicKey.getAlgorithm();
Signature signatureInstance = Signature.getInstance(signatureAlgorithm);
signatureInstance.initVerify(publicKey);
byte[] messageBytes = Base64.encodeBase64(message.getBytes(UTF_8));
signatureInstance.update(messageBytes);
byte[] receivedSignature = Base64.decodeBase64URLSafe(signature);
return signatureInstance.verify(receivedSignature);
(为简洁起见,我删除了上面的异常处理和资源关闭。我使用的是 tomcat 的 Base64 类。)
代码运行没有错误,但表明签名无效。在我看来,以下任何一项都可能是错误的:
- 从 ADFS 服务器提取的公钥都不是相关的公钥。
- 公钥从 .cer 到 .pem 的转换可能不正确。
- 验证签名或加载公钥的代码可能是错误的。
解决方案
推荐阅读
- docker - 如何忽略要在 docker build 上下文中发送的文件夹
- ruby-on-rails - Rails:如何管理“静态”时间值属性?
- flutter - 限制 Flutter WebView 插件中的 URL 可访问性
- python - 长标题崩溃 django 站点 error500
- docker - 如何将大型 docker 映像部署到 Pivotal Cloud Foundry
- java - 我在 android studio 上有一个 R.Layout.main 错误
- javascript - 如何在 DOM 中获取附近的元素
- typescript - 在 Apollo typeDefs 中使用 TypeScript 接口和类型
- php - WooCommerce - 如何使用具有相同添加到购物车按钮的 ajax 将多个不同的产品添加到购物车?
- angularfire - 错误:在 Angular Firebase Universal 中找不到模块 'require("./server/main")'