You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

passport-saml无法找到签名:Response ID与Reference URI不匹配

解决passport-saml与JumpCloud集成时的「Invalid document signature」错误

问题重现

使用passport-saml对接JumpCloud做SAML认证时,触发「Invalid document signature」错误。调试发现代码里的signatures数组为空,进而触发判断:

if (signatures.length !== 1) {return false;}

根因分析

SAML响应的签名结构不匹配passport-saml的默认验证逻辑:

  • <saml2p:Response>节点的ID为K0WO32GJF96P5SJBU9I5V0YI53OBOCIUSG6G4RX9
  • 签名部分的<ds:Reference>节点的URI指向的是<saml2:Assertion>的ID:#Q65FHLGKK1SSG05I7UWVEQS5URLD0EUVKIP0GY06

passport-saml的默认签名验证逻辑会以当前处理节点(这里是Response)的ID构造XPath查询,去匹配<ds:Reference>的URI,因此找不到对应签名,导致signatures数组为空,验证失败。

解决方案

方案1:修改JumpCloud配置,让IDP签名整个Response

登录JumpCloud控制台,找到对应的SAML应用配置:

  • 找到「签名选项」相关设置,将签名对象从「Assertion」改为「Response」
  • 保存配置并重新发起认证请求

方案2:修改passport-saml的验证逻辑,指定验证Assertion的签名

在passport-saml的配置中,自定义签名验证逻辑或指定验证目标为Assertion:

const samlStrategy = new SamlStrategy(
  {
    // 其他现有配置
    validateInResponseTo: false,
    signatureValidationCert: '你的JumpCloud证书',
    // 自定义签名查找逻辑,定位到Assertion节点
    getSignedAssertion: (response) => {
      // 从SAML响应中提取Assertion节点并返回
      const xmlDoc = new DOMParser().parseFromString(response, 'text/xml');
      return xmlDoc.querySelector('saml2:Assertion').outerHTML;
    }
  },
  (profile, done) => {
    // 认证回调逻辑
  }
);

如果默认配置不支持直接指定验证Assertion,也可以修改passport-saml源码中的签名查询XPath,将基于Response ID的查询改为匹配Assertion ID的查询:

//ds:Signature[ds:SignedInfo/ds:Reference[@URI='#{$assertionId}']]

内容的提问来源于stack exchange,提问作者Curious

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 08:47:17