验证 Azure AD 令牌签名失败 JAVA

2023-11-22

我正在努力验证 Azure AD 令牌签名。

当我在“jwks_uri”字段中查找正确的密钥描述时

https://login.microsoftonline.com/common/.well-known/openid-configuration

我检查了所属的关键数据。

我尝试使用“n”-模数和“e”字段来生成用于签名验证的公钥,但最终出现错误:

BASE64Decoder decoder = new BASE64Decoder();        
byte[] modulusBytes = decoder.decodeBuffer(n);
byte[] exponentBytes = decoder.decodeBuffer(e);

BigInteger modulusInt = new BigInteger(1, modulusBytes);
BigInteger exponentInt = new BigInteger(1, exponentBytes);

try {
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(modulusInt, exponentInt);
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(publicSpec);
Jwt<Header, String> c = Jwts.parser().setSigningKey(pubKey).parsePlaintextJwt(token);

} catch (Exception ex) {
  ex.printStackTrace();
}

Console:

io.jsonwebtoken.SignatureException: Unable to verify RSA signature using configured PublicKey. Signature length not correct: got 256 but was expecting 246
at io.jsonwebtoken.impl.crypto.RsaSignatureValidator.isValid(RsaSignatureValidator.java:50)
at io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator.isValid(DefaultJwtSignatureValidator.java:47)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:351)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481)
at io.jsonwebtoken.impl.DefaultJwtParser.parsePlaintextJwt(DefaultJwtParser.java:503)
at com.ge.hc.pfh.poc.ams.filter.JwtFilter.doFilter(JwtFilter.java:120)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at com.ge.hc.pfh.poc.ams.filter.ApiOriginFIlter.doFilter(ApiOriginFIlter.java:28)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at com.ge.hc.pfh.poc.ams.filter.MDCFilter.doFilter(MDCFilter.java:34)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

我尝试了另一种方法来使用“x5c”字段,它是一个 Base 64 编码的证书链:

byte[] certChain = Base64.getDecoder().decode(x5c);
X509Certificate cert = X509CertUtils.parse(certChain);
PublicKey pubKeyNew = cert.getPublicKey();
Claims claims3 = Jwts.parser()
          .setSigningKey(pubKeyNew)
            .parseClaimsJws(token).getBody();

我最终遇到了另一个错误:

io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:354)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481)
at io.jsonwebtoken.impl.DefaultJwtParser.parsePlaintextJwt(DefaultJwtParser.java:503)
at com.ge.hc.pfh.poc.ams.filter.JwtFilter.doFilter(JwtFilter.java:106)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at com.ge.hc.pfh.poc.ams.filter.ApiOriginFIlter.doFilter(ApiOriginFIlter.java:28)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at com.ge.hc.pfh.poc.ams.filter.MDCFilter.doFilter(MDCFilter.java:34)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

有人知道我做错了什么吗? 谢谢。


第一个例子

模数和指数 (n and e) in https://login.microsoftonline.com/common/discovery/keys被编码在base64url并且不在base64,所以解码它们的代码应该是

byte[] modulusBytes = Base64.getUrlDecoder().decode(n);
BigInteger modulusInt = new BigInteger(1, modulusBytes);

不要使用旧的com.sun.misc.BASE64Decoder

如果 JWT 已签名,则不应使用JWTParser.plaintextJwt()。根据文档

plaintextJwt:紧凑的序列化无符号明文 JWT 字符串

改用parseClaimsJws or parsePlaintextJws。仅当有效负载是非 JSON 字符串时才使用第二种方法

第二个例子

第二个例子基本是对的。我假设X509CertUtils.parse(certChain)类似于

 InputStream in = new ByteArrayInputStream(certChain);
 CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
 X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);

证书的模数和指数与解码后的相同,因此公钥是等效的

链接中有两个类似的证书,请检查两个。您应该能够验证签名。如果不是,则令牌未使用这些密钥进行签名

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

验证 Azure AD 令牌签名失败 JAVA 的相关文章

  • Libgdx SpriteBatch.draw() 指定 4 个顶点

    我正在使用 libGdx 创建一个 2d 游戏 并尝试使用这个特殊的方法来绘制一个简单的 2d 纹理 分别指定 4 个顶点 draw Texture texture float spriteVertices int offset int l
  • HTTP按需触发azure函数多次调用自身

    我添加了http触发的azure函数并将其部署在函数应用程序中 函数应用程序仅包含一个此 http 按需触发器 azure 函数 功能应用程序有应用程序服务计划 而不是消费计划 另外 函数应用程序版本为 1 所以超时是无限的 在天蓝色的函数
  • jdbctemplate计数queryForInt并传递多个参数

    如何传入多个参数jdbcTemplate queryForInt得到计数 我试过这个 Integer count this jdbcTemplate queryForInt select count name from table name
  • 如何使用 JNDI 和 Digest-MD5 对 LDAP 进行身份验证

    我正在尝试使用 DIGEST MD5 加密对 LDAP 服务器进行身份验证 使用简单加密时 它工作得很好 但由于显而易见的原因 我无法通过网络以纯文本形式发送密码 奇怪的是 在使用 Softerra LDAP 浏览器时 我可以使用 Dige
  • 执行 SET {Key} 超时,inst: 0,mgr: Inactive,queue: 2, qu=1, qs=1, qc=0, wr=1/1, in=0/0

    我正在尝试使用 StackExchange Redis 客户端将 90 KB pdf 文件保存到 Azure Redis 缓存中 我已将该文件转换为字节数组并尝试使用 stringSet 方法保存它并收到错误 Code byte bytes
  • 在 JUnit 中使用 Spring 测试服务时如何回滚数据库事务?

    我测试我的 DAO 和服务没有问题 但是当我测试时INSERTs or UPDATE我想回滚事务而不影响我的数据库 我在用着 Transactional在我的服务中管理交易 我想知道 是否有可能知道事务是否正常 但回滚它以防止更改数据库 这
  • java.lang.NoClassDefFoundError:org.apache.batik.dom.svg.SVGDOMImplementation

    我在链接到我的 Android LibGDX 项目的 Apache Batik 库时遇到了奇怪的问题 但让我们从头开始 在 IntelliJ Idea 中我有一个项目 其中包含三个模块 Main Android 和 Desktop 我强调的
  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 在 Azure Pipeline 中出现“在默认池中找不到满足指定需求的代理”错误

    我对 Azure DevOps 还比较陌生 我在 Windows 2016 服务器上安装了 Azure DevOps Server 2019 我使用经典编辑器创建了一个 Azure 管道 我的代理作业有四个步骤 安装节点 npm insta
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat

随机推荐