Sunday, April 10, 2016

Connect to SSL SOAP Host via “Service Reference” and pass Security Header

Leave a Comment

I am trying to connect to a SSL SOAP service host by C# using Service Reference. This is my request message:

<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/zwMmtdsVhFsAVDkQbiV/4AAAAA1zXtnc72UEm+4tlKzvCxsvN6OC2prvRIljIX4XzHKEYACQAA</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-18T12:45:27.558Z</u:Created>                 <u:Expires>2016-03-18T12:50:27.558Z</u:Expires>             </u:Timestamp>             <o:UsernameToken u:Id="uuid-2c7986ba-eee5-4411-90a9-a02b625c55ff-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">MyPlainPassword</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">         <generateId xmlns="http://com.vedaadvantage/dp3/Enterprise/StandardTradeCreditCommercial/IndividualCommercialService"/>     </s:Body> </s:Envelope> 

This is the message that my service sends to the host. But the host returns as below:

Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.

This is my config file:

<?xml version="1.0" encoding="utf-8" ?> <configuration>    <system.serviceModel>      <bindings>       <customBinding>         <binding name="myBinding">           <textMessageEncoding messageVersion="Soap11" />           <security  authenticationMode="UserNameOverTransport"                      messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10" >           </security>            <httpsTransport />         </binding>       </customBinding>     </bindings>     <client>       <endpoint address="https://{URL}"         binding="customBinding"                 bindingConfiguration="myBinding"         contract="ServiceReference2.MyService"                 name="IndividualCommercialService" />     </client>   </system.serviceModel> </configuration> 

Although when I send the same XML via SOAPUI or other HTTP Post methods it works fine.

I also extract and attached the certificate and user/pass as below:

private static X509Certificate2 DownloadSslCertificate(string strDNSEntry)         {              X509Certificate2 cert = null;             using (TcpClient client = new TcpClient())             {                 //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;                            client.Connect(strDNSEntry, 443);                  SslStream ssl = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);                 try                 {                     ssl.AuthenticateAsClient(strDNSEntry);                 }                 catch (AuthenticationException e)                 {                     //log.Debug(e.Message);                     ssl.Close();                     client.Close();                     return cert;                 }                 catch (Exception e)                 {                     //log.Debug(e.Message);                     ssl.Close();                     client.Close();                     return cert;                 }                 cert = new X509Certificate2(ssl.RemoteCertificate);                 ssl.Close();                 client.Close();                 return cert;             }         }          private static void Main(string[] args){                 var proxy = new MyService();                  var uri = proxy.Endpoint.Address.Uri;                 var cer = DownloadSslCertificate(uri.DnsSafeHost);                  EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity(cer.Subject.Replace("CN=", ""));                 EndpointAddress address = new EndpointAddress(proxy.Endpoint.Address.Uri, identity);                  proxy.Endpoint.Address = address;                  proxy.ClientCredentials.UserName.UserName = "MyUserName";                 proxy.ClientCredentials.UserName.Password = "MyPlainPassword";                 proxy.ClientCredentials.ServiceCertificate.DefaultCertificate = cer;                  proxy.HellowWorld();           } 

I am not sure whether the method that I am getting the certificate is correct or not and also why HTTP Post works but my Service Reference Call does not.

Thanks in advance for your help.

Cheers

1 Answers

Answers 1

Try to look inside WSDL (Service References) in order to see hidden files first select Show All Files in Solution explorer. You`ll se inside service reference Reference.svcmap -> Reference.cs, and inside of this file add ProtectionLevel = System.Net.Security.ProtectionLevel.Sign as shown below

[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.your.url/Service/", ConfigurationName = "Service.Service", ProtectionLevel = System.Net.Security.ProtectionLevel.Sign)] 

that should help you. Usually it`s really bad idea to modify autogenerated proxy, but seems like that is the only option.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment