I have a WCF client with TransportWithMessageCredential security mode. When try to log request using BeforeSendRequest
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\tmp\\request_log.xml");
file.WriteLine(request.ToString());
file.Close();
return null;
}
have result without security tags
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://(skiped)</Action>
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>
How can I log full raw request in client? It must be like this
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>...</u:Created>
<u:Expires>..</u:Expires>
</u:Timestamp>
<o:BinarySecurityToken>
<!-- Removed-->
</o:BinarySecurityToken>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
...
</SignedInfo>
<SignatureValue>...</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
...
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">skiped</Action>
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>
UPD. Security options for binding
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" algorithmSuite="Basic256" />
</security>
I didn't found how to do this in C# but had captured raw request using
Charles SSL proxying
The request contains all security tags.
The article which helped me so much Tracing-WCF-Messages
This may help:
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
Log("Request:" + Environment.NewLine + buffer.CreateMessage());
return null;
}
You can also use Fiddler which is free.
If your endpoint is https be sure to bypass certificate validation with this
ServicePointManager.ServerCertificateValidationCallback = delegate {return true;};
because Fiddler uses its own certificate that is invalid for your connection.
Related
I need some help to consume a web service using SOAP.
My application use .NET 4.0.
The SOAP request have to follow the following requirments :
Transport protocol : HTTPS
Encryption and authentication is carried out via SSL v3/TLS v1.0
The message need to be signed. (WS-Security 1.1, http://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718, PKCS#1 v1.5, RSA-SHA256)
I have to use two differents certificats for encryption and signing.
The WCF configuration should be configurable (the signature can be desactivated). So the bindings have to be created in c# code and not in app.config.
Sample of request expected by the server :
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-C6D119F21B41F79DBF154885449980234">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="s" />
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<ds:Reference URI="#id-5">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
<ds:KeyInfo Id="KI-C6D119F21B41F79DBF154885449979232">
<wsse:SecurityTokenReference wsu:Id="STR-C6D119F21B41F79DBF154885449979233">
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=..,O=...,C=..</ds:X509IssuerName>
<ds:X509SerialNumber>...</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</s:Header>
<s:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-5">
...
</s:Body>
</s:Envelope>
My first attempt was to generate and send the request using WCF but I didn't find out how to generate something following the requirement.
Then I try to generate the signature manually and use an IClientMessageFormatter and a IEndpointBehavior to create the header manualy.
This solution didn't work because WCF applies treatments (switching xml attributes and namespaces...) that invalidates the signature.
My last attempt was to completly remove WCF and send the request manualy but HttpClient is not available in .NET 4.0 and I didn't find out how to send TLS request without it.
Can anyone tell me how to configure WCF to generate the right SOAP request ?
If the request can't be created with WCF, how can I send TLS request (and handle a responce) with .NET 4.0?
Thanks.
As far as I know, header could be configured in web.config or app.config.
<endpoint address="http://ws-wuxipc-5077:4000/calculator" binding="basicHttpBinding"
contract="ServiceInterface.ICalculatorService" name="cal">
<headers>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>
</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">monMonDePasse</wsse:Password>
<wsse:Nonce>sdsdsdlojhfdsdM5Nw==</wsse:Nonce>
<wsu:Created>2019-01-21T6:17:34Z</wsu:Created>
</wsse:UsernameToken>
</Security>
</headers>
</endpoint>
You could also add header in your code through xml.
using (ChannelFactory<ICalculatorService> ChannelFactory = new ChannelFactory<ICalculatorService>("cal"))
{
// ChannelFactory.Endpoint.EndpointBehaviors.Add(new MyEndpointBehavior());
ICalculatorService employeeService = ChannelFactory.CreateChannel();
using (OperationContextScope scope = new OperationContextScope((IContextChannel)employeeService))
{
System.Xml.XmlDocument document = new XmlDocument();
XmlElement element = document.CreateElement("wsse", "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
XmlElement newChild = null;
newChild = document.CreateElement("wsse", "Username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
newChild.InnerText = "finance";
element.AppendChild(newChild);
newChild = document.CreateElement("wsse", "password", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
newChild.SetAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
newChild.InnerText = "387";
element.AppendChild(newChild);
MessageHeader messageHeader = MessageHeader.CreateHeader("security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", element, false);
OperationContext.Current.OutgoingMessageHeaders.Add(messageHeader);
employeeService.Add(5, 6);
}
// List<Employee> list= employeeService.GetList();
Console.Read();
}
I am trying to make a SOAP call to a webservice.
According to the manual the SOAP call should look like this:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wsswssecurity-secext-1.0.xsd"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:vh="http://vedaxml.com/soap/header/v-header-v1-9.xsd"
xmlns:idm="http://vedaxml.com/vxml2/idmatrix-v4-0.xsd">
<soapenv:Header>
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>****</wsse:Username>
<wsse:Password>****</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous
</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://vedaxml.com/sys2/idmatrix-v4</wsa:To>
<wsa:Action>http://vedaxml.com/idmatrix/VerifyIdentity</wsa:Action>
<wsa:MessageID>Quick_Request_1</wsa:MessageID>
</soapenv:Header>
<soapenv:Body>
<idm:request client-reference="Quick Connect Ref"
reason-for-enquiry="Quick Connect">
<idm:individual-name>
<idm:family-name>Potter</idm:family-name>
<idm:first-given-name>Harry</idm:first-given-name>
<idm:other-given-name>James</idm:other-given-name>
</idm:individual-name>
<idm:date-of-birth>1980-07-31</idm:date-of-birth>
<idm:current-address>
<idm:property>Potter Manor</idm:property>
<idm:unit-number>3</idm:unit-number>
<idm:street-number>4</idm:street-number>
<idm:street-name>Privet</idm:street-name>
<idm:street-type>Drive</idm:street-type>
<idm:suburb>Little Whinging</idm:suburb>
<idm:state>NSW</idm:state>
<idm:postcode>2999</idm:postcode>
</idm:current-address>
</idm:request>
</soapenv:Body>
</soapenv:Envelope>
The company has provided me with a WSDL file. Which I have imported into C# as both a Service Reference and a Web Reference (Because I couldnt get service reference working)
First of all I tried a Service Reference, no bindings were created in web.config when I imported the WSDL file, So I programmatically added the bindings. This is my code:
BasicHttpsBinding binding = new BasicHttpsBinding(securityMode: BasicHttpsSecurityMode.TransportWithMessageCredential);
EndpointAddress address = new EndpointAddress("https://ctaau.vedaxml.com/cta/sys2/idmatrix-v4");
ServiceReference1.identitydetails idDetails = new ServiceReference1.identitydetails();
ServiceReference1.IdMatrixPortTypeClient client = new ServiceReference1.IdMatrixPortTypeClient(binding, address);
ServiceReference1.request request = new ServiceReference1.request();
request.individualname = new ServiceReference1.individualnameType();
request.individualname.familyname = "Doe";
request.individualname.firstgivenname = "John";
request.dateofbirth = new DateTime(1982, 6, 30);
client.ClientCredentials.UserName.Password = "myPassword";
client.ClientCredentials.UserName.UserName = "myUsername";
var response = client.IdMatrixOperation(request);
The resposne failed, so I checked the POST with Fiddler. It was coming up completely different to the required post.
Fiddler showed me:
POST https://ctaau.vedaxml.com/cta/sys2/idmatrix-v4 HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://vedaxml.com/idmatrix/VerifyIdentity"
Host: ctaau.vedaxml.com
Content-Length: 1216
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo/2Z+y84o0RBobFBWyoF5bwAAAAAMq+GwwIcokm+lVAU/kPq4mJScS+4yh9ElAQSyM2iUqMACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2016-03-23T01:23:53.921Z</u:Created>
<u:Expires>2016-03-23T01:28:53.921Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-f3068a37-421c-4b81-93c6-ef622def918a-1">
<o:Username>myUsername</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">myPassword</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<request xmlns="http://vedaxml.com/vxml2/idmatrix-v4-0.xsd">
<individual-name>
<family-name>Doe</family-name>
<first-given-name>John</first-given-name>
</individual-name>
</request>
</s:Body>
</s:Envelope>
As you can see the WSSE name space is incorrect. I dont have WS-Addressing and The Prefix's are all wrong?
So then I moved to A Web Reference. I needed to get WS-Secrutiy working, so I changed the client protocol to WebServicesClientProtocol.
This is my code:
WebReference.idmatrix idMatrix = new WebReference.idmatrix();
WebReference.request request = new WebReference.request();
request.individualname = new WebReference.individualnameType();
request.individualname.familyname = "Potter";
request.individualname.othergivenname = names;
request.individualname.firstgivenname = "Harry";
request.dateofbirth = new DateTime(1980, 7, 31);
UsernameToken userToken = new UsernameToken("myusername", "mypassword", PasswordOption.SendPlainText);
SoapContext requestContext = idMatrix.RequestSoapContext;
requestContext.Security.Tokens.Add(userToken);
var test = idMatrix.IdMatrixOperation(request);
The Post in fidder looks like:
POST https://vedaxml.com/sys2/idmatrix-v4 HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0.30319.42000)
VsDebuggerCausalityData: uIDPo+bosvSda9ZIvNIXrG1tEbIAAAAAH4GKWz0+uU2A4pOErBrkw2fytXzxQh9Jp4TpqUiqXHoACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://vedaxml.com/idmatrix/VerifyIdentity"
Host: vedaxml.com
Content-Length: 1768
Expect: 100-continue
Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>http://vedaxml.com/idmatrix/VerifyIdentity</wsa:Action>
<wsa:MessageID>uuid:d1a0cf65-cee3-467d-9f98-b72cbd3d4e5a</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>https://vedaxml.com/sys2/idmatrix-v4</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-5fbc1707-8d36-4091-804d-4c19ec06f7bd">
<wsu:Created>2016-03-23T01:26:31Z</wsu:Created>
<wsu:Expires>2016-03-23T01:31:31Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-4803d49a-e2c3-45f5-bf18-7c0b5cd7d130">
<wsse:Username>myusername</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">mypassword</wsse:Password>
<wsse:Nonce>sc5Dgf/vhU+YTZjdLQZsLw==</wsse:Nonce>
<wsu:Created>2016-03-23T01:26:31Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<request xmlns="http://vedaxml.com/vxml2/idmatrix-v4-0.xsd">
<individual-name>
<family-name>Potter</family-name>
<first-given-name>Harry</first-given-name>
<other-given-name>James</other-given-name>
</individual-name>
</request>
</soap:Body>
</soap:Envelope>
Its a little closer, but some of the namespaces are still wrong, and the prefexis are wrong too.
It needs to be soapenv: and in the body needs to be idm:
How can I fix the namespaces and prefix's in C#?
So I finally solved my problem. I will post everything I have learnt. First of all, Prefix's do not mean anything.
and are the same thing, the prefix only relates to the namespace ie:
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" = <s:envelope>
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" = <soap:envelope>
both of these are equivalent.
Secondly what I needed to do was get WS-Security and WS-Addressing and Soap V1.1 (not v1.2) working as this was required by the server.
To do this, I had to create a custom binding. In Web.config:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="WsHttpSoap11">
<textMessageEncoding messageVersion="Soap11WSAddressing10"></textMessageEncoding>
<security authenticationMode="UserNameOverTransport"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11"
securityHeaderLayout="Lax"
includeTimestamp="false"
requireDerivedKeys="false" >
</security>
<httpsTransport></httpsTransport>
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="<my endpoint url>" binding="customBinding" bindingConfiguration="WsHttpSoap11" contract="ServiceReference1.IdMatrixPortType" name="testBinding" ></endpoint>
</client>
I checked the output with Fiddler, and all the correct namespaces were being created.
In conclusion, I hope everyone in the future moves away from SOAP and runs towards Oauth + RESTfull applications.
I've a problem to get a token from the STS. I get the token if I use SoapUI. But I don't know how to configure my client application that it creates a request like:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>
<a:To s:mustUnderstand="1">https://.../idp/sts.wst</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken>
<o:Username>xxxUSERxxx</o:Username>
<o:Password>xxxPWxxx</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<trust:RequestSecurityToken Context="http://client.ws.com" xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<a:EndpointReference>
<a:Address>xxxADDRESSxxx</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
<trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
<trust:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</trust:TokenType>
</trust:RequestSecurityToken>
</s:Body>
</s:Envelope>
Can anybody help me?
Does the STS expose a metadata exchange endpoint? If so you could create a client proxy via visual studio's "add service reference" dialogue (or just use svcutil).
You could use this article as a starting point.
In order to unit test a class for handling WCF responses, I snagged an actual Message Response using Message.ToString() so that I don't have to actually make the WCF call (thus making it an integration test rather than a unit test). How do I re-construct a Message object based on that SOAP XML that comes from the Message.ToString() output, or is it even possible? I don't know which Message.CreateMessage() overloads addresses this situation.
Here's the result of the Message.ToString():
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1" u:Id="_4">http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse</a:Action>
<a:RelatesTo u:Id="_5">urn:uuid:3c4e24a9-af47-4f4a-879a-04a5e0296cd5</a:RelatesTo>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="uuid-73a747a6-ffda-43f2-908d-4e1d9ad52eed-1810">
<u:Created>2013-06-05T17:11:39.734Z</u:Created>
<u:Expires>2013-06-05T17:16:39.734Z</u:Expires>
</u:Timestamp>
<c:DerivedKeyToken u:Id="_0" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
<o:SecurityTokenReference>
<o:Reference URI="urn:uuid:368c80e4-4044-4b00-8da4-8ba6c9f7c8d6" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
</o:SecurityTokenReference>
<c:Offset>0</c:Offset>
<c:Length>24</c:Length>
<c:Nonce>lnBkV4BtA6KOTkUGykrSyw==</c:Nonce>
</c:DerivedKeyToken>
<c:DerivedKeyToken u:Id="_1" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
<o:SecurityTokenReference>
<o:Reference URI="urn:uuid:368c80e4-4044-4b00-8da4-8ba6c9f7c8d6" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
</o:SecurityTokenReference>
<c:Nonce>oA/QSxlAEfZnE4Z3OgPX+w==</c:Nonce>
</c:DerivedKeyToken>
<e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:DataReference URI="#_3" />
<e:DataReference URI="#_6" />
</e:ReferenceList>
<e:EncryptedData Id="_6" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<o:Reference URI="#_1" />
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>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</e:CipherValue>
</e:CipherData>
</e:EncryptedData>
</o:Security>
</s:Header>
<s:Body u:Id="_2">
<EnumerateResponse xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EnumerationContext>
<CurrentIndex xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">0</CurrentIndex>
<EnumerationDirection xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">Forwards</EnumerationDirection>
<Expires xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">9999-12-31T23:59:59.9999999</Expires>
<Filter xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">/Person</Filter>
<LocalePreferences xsi:nil="true" xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement" />
<Selection xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">
<string>ObjectID</string>
</Selection>
<Sorting xsi:nil="true" xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement" />
</EnumerationContext>
<EnumerationDetail xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">
<Count>926</Count>
</EnumerationDetail>
<Expires>12/31/9999 23:59:59</Expires>
</EnumerateResponse>
</s:Body>
</s:Envelope>
So, how do I construct a Message out of that?
If you have the whole envelope of a message, you can create the Message object by using the overload Message.CreateMessage(XmlDictionaryReader, int, MessageVersion). Create a XmlDictionaryReader over the contents of the message by using a code similar to this one:
var bytes = Encoding.UTF8.GetBytes(theMessageString);
var reader = XmlDictionaryReader.CreateTextReader(bytes, XmlDictionaryReaderQuotas.Max);
Now, the message you have has some timestamps, is encrypted and signed. It's possible that once you pass it to WCF, it will be invalid...
You'll find instructions at the link below for creating an XSD from the XML, then creating a new class from the XSD.
Generate C# class from XML
Create an instance of this object, and serialize it to generate the new XML:
public class SoapThing
{
...
}
SoapThing p=new SoapThing ();
p.x = some values;
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(p.GetType());
x.Serialize(Console.Out, p);
I'm trying to get a WCF client to call a web service with security information provided in the SOAP Header of the request, as follows.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ah_etas_order="http://types.defra.gov.uk/ahw/eartagging/order"
xmlns:ah_common="http://types.defra.gov.uk/ahw/common/complextypes"
xmlns:ah_assettype="http://types.defra.gov.uk/ahw/asset"
xmlns:ah_ref_data_sets="http://types.defra.gov.uk/ahw/common/referencedatasets"
xmlns:ah_custtype="http://types.defra.gov.uk/ahw/customer"
xmlns:m5="http://types.defra.gov.uk/bs7666"
xmlns:m6="http://www.govtalk.gov.uk/people/bs7666"
xmlns:m7="http://types.defra.gov.uk/ahw/common/derivedtypes"
xmlns:ah_etas_type="http://types.defra.gov.uk/ahw/eartagging">
<SOAP-ENV:Header xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Security soap:role="system" soap:mustUnderstand="true">
<wsse:UsernameToken>
<wsse:Username>username here</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password here</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>...</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I'm using Visual Studio 2012 and .NET 4. The docs say the version of SOAP messaging used for CARA Services is SOAP 1.2.
I've added a service reference with has added a web.config file with an endpoint and the following custom binding.
<customBinding>
<binding name="ProcessOrderBinding">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
I've tried lots of different web.config options but can't seem to get the correct soap header. Can anyone point me in the right direction?
Update:
#Yaron, Here is the soap header using your binding. I've added a includeTimestamp=false to remove the timestamp.
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">
uIDPoxqYDT0sMwVImscgqVaf7GYAAAAAjin6KftLjkaS2CW99IXxrnWGCjfQnzFFuf4zGaQpeqIACQAA
</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-79885712-d6eb-451c-9483-4df2b68722bd-1">
<o:Username>username here</o:Username>
<o:Password>password here</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">...</s:Body>
</s:Envelope>
As you can see it's missing the following before the password.
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
Use this binding:
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap12" />
<security authenticationMode="UserNameOverTransport">
<secureConversationBootstrap />
</security>
<httpsTransport />
</binding>
</customBinding>
Of course you also need to supply user/pass on the proxy:
proxy.ClientCredentials.Username.Username = "user"
proxy.ClientCredentials.Username.Password = "pass"
All this assumes you also use SSL. If you don't then check out CUB.