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
相关产品推荐
相关产品推荐

