I need to communicate with a WebService through XML. This service is using a saml:Assertion to authenticate the connection. I can communicate with the server, but the validation always fails. I searched for hours what the problem is, because when I use soapUI with the exact same parameters and saml ticket, it works. I tried to "manually" remove any formatting from the saml:Assertion because it was signed, so with a single-byte change, it won't work anymore.
Here's my code:
// Insert saml:Assertion string into soapenv:Header
private static void InsertSAML(ref XmlDocument soapXML, ref XmlNamespaceManager nsmgr, string saml)
{
// Remove all formatting
saml = saml.Replace("\r", "");
saml = saml.Replace("\n", "");
while(saml.IndexOf(" ") > -1)
{
saml = saml.Replace(" ", " ");
}
saml = saml.Replace("> <", "><");
saml = saml.Replace("\" />", "\"/>");
XmlElement soapHeader = (XmlElement)soapXML.SelectSingleNode("//soapenv:Envelope/soapenv:Header/wsse:Security", nsmgr);
if (soapHeader == null)
{
throw new Exception("Can't find \"//soapenv:Envelope/soapenv:Header/wsse:Security\"");
}
soapHeader.InnerXml += saml;
}
But it seems like when I use soapHeader.InnerXml += saml;
it causes some kind of formatting. A whitespace will appear before the closing tags of elements without inner content:
So, I need to add this:
<dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
But in the final XML looks like this, even if I replaced these occurences before inserting:
<dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
How can I get rid of this behaviour?
As I said, the problem was with the additional bytes XmlDocument added to my xml when I append content to the InnerXml. I tried so hard to remove all formatting, and it was a good direction. But instead of "un-formatting" the saml:Assertion part, I magaged to un-format the whole request body, right before it was sent to the service. And now it works. I call this method right before sending the request:
// Insert XML to request body
private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (var stringWriter = new StringWriter())
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
using (Stream stream = webRequest.GetRequestStream())
{
// Get XML contents as string
soapEnvelopeXml.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
string str = stringWriter.GetStringBuilder().ToString();
// Remove all formatting
str = str.Replace("\r", "");
str = str.Replace("\n", "");
while (str.IndexOf(" ") > -1)
{
str = str.Replace(" ", " ");
}
str = str.Replace("> <", "><");
str = str.Replace("\" />", "\"/>");
// Write the unbeutified text to the request stream
MemoryStream ms = new MemoryStream(UTF8Encoding.Default.GetBytes(str));
ms.WriteTo(stream);
}
}