我们的IdP是Salesforce.com组织。 SP是第三方.Net应用程序。在开发过程中,第三方报告说他们无法验证发送的SAML响应。
我们决定尝试使用ComponentSpace验证SAML响应。以下是我们的尝试:
// Load the certificate from the file: certInFile
// Load the SAML in an XMLElement: samlXml
// Retrieve the certificate from the SAML: certInSaml
Console.WriteLine("SAML is valid ? " + SAMLResponse.IsValid(samlXml));
Console.WriteLine("Is SAML signed? " + SAMLMessageSignature.IsSigned(samlXml));
Console.WriteLine("Certificate found in SAML is same as certificate file? " + certInFile.Equals(certInSaml));
Console.WriteLine("Validated SAML with certificate found in SAML" + SAMLMessageSignature.Verify(samlXml, certInSaml));
Console.WriteLine("Validated SAML with certificate file" + SAMLMessageSignature.Verify(samlXml, certInFile));
除了最后两个,我对上述所有事情都是如此。所以:
从3,4我们可以得出结论,Salesforce正在签署但是使用不同的证书但在响应中发送了错误的公钥吗?!
修改:示例SAML在此http://pastebin.com/J8FTxnhJ
我错过了什么?
答案 0 :(得分:4)
XML签名验证失败,因为签名后修改了XML或者使用了错误的证书来验证签名。最可能的情况是使用了错误的证书。
Salesforce使用其私钥对SAML响应进行签名。使用Salesforce管理控制台,您可以下载应该用于执行签名验证的相应公钥/证书。
调用SAMLMessageSignature.Verify
时,您可以指定用于执行验证的X509Certificate
,这通常是您应该做的。
但是,base-64编码的X.509证书也嵌入在XML签名中。您可以使用此嵌入式证书来检查签名是否验证。
为此,请勿将X509证书传递给SAMLMessageSignature.Verify
。
例如:SAMLMessageSignature.Verify(samlXml, null);
如果有效但指定证书失效,则确认使用了错误的证书。
您可以调用SAMLMessageSignature.GetCertificate
从XML签名中检索X.509证书,以将其与正在使用的证书进行比较。
另外,作为旁注,XML签名适用于XML。无法使用HTTP Post数据中发送的base-64编码的SAML响应直接验证它们。在尝试验证XML签名之前,必须将后期数据解码为XML。
答案 1 :(得分:1)
当我们没有解码生成的base64编码的SAML但直接尝试验证它时,这是有效的。但是,仍然不确定为什么ComponentSpace方法报告的解码字符串不同。
答案 2 :(得分:0)
我知道这是一篇过时的文章,但是我遇到了同样的问题,并对未回答感到不满意。对于那些正在遇到此问题并通过Internet搜索找到此页面作为使用ComponentSpace进行Salesforce SAML签名验证失败的唯一结果之一的人,该问题可能不在SAML签名验证本身内,而是您如何解码base-64编码的SAML响应有效负载。
请注意,采用SAMLServiceProvider.ReceiveSSO()
的{{1}}方法不会遇到此问题。我发现这是在手动解码可能触发此问题的有效负载时,具体取决于IdP签名响应时XML的格式。
由于这是一篇较旧的文章,并且pastebin链接已不复存在,因此我们假设原始代码可能如下所示。 (还假设X.509证书已嵌入有效负载中,但最终的解决方法是相同的。)
HttpRequest
对于Salesforce(可能还有其他),xcert将为非null,isSigned和isValid设置为true,但是isVerified将为false。上面的代码简单,难以捉摸吗? var str = Encoding.UTF8.GetString(Convert.FromBase64String(samlResponse));
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(str);
var xcert = SAMLMessageSignature.GetCertificate(xdoc.DocumentElement);
var isSigned = SAMLMessageSignature.IsSigned(xdoc.DocumentElement);
var isValid = SAMLResponse.IsValid(xdoc.DocumentElement);
var isVerified = SAMLMessageSignature.Verify(xdoc.DocumentElement);
原因是因为签名是基于原始XML结构(或其某些子节)生成的。如果IdP在其原始SAML XML中包含空格,则即使在XML中通常可以忽略空格,也将其包括在签名生成中。这就是为什么签名验证失败时IsValid仍返回true的原因。
最后一个方便的注释被埋在ComponentSpace的示例代码中,完整的 safe XmlDocument转换是:
xdoc.PreserveWhitespace = true;
对于我们的情况,我们不需要在使用XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.DtdProcessing = DtdProcessing.Ignore;
xmlReaderSettings.XmlResolver = null;
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.PreserveWhitespace = true;
xmlDocument.XmlResolver = null;
using (XmlReader xmlReader = XmlReader.Create(new StreamReader(fileName), xmlReaderSettings))
{
xmlDocument.Load(xmlReader);
}
的额外步骤中包含DtdProcessing.Ignore
,而是将其包含在此解决方案中以涵盖所有用例。