Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Sign WCF Message With Certificate Using HTTPS Transport with Client Certificate

EDIT:

I finally determined that IClientMessageInspector does not seem to reflect message signing so when I was actually getting a signature in my request I didn't know it. So now for my new, real question...

How can I configure a WCF client to present both the SSL client cert and sign the SOAP Header?

var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;

This will result in the header having a timestamp that's signed. However, the client cert is no longer presented and I don't get past SSL. If I change the second line to:

myBinding.Security.Mode = BasicHttpSecurityMode.Transport;

Then I get past SSL but my SOAP header no longer has the signing block.

Is there any way I can get ahold of HttpWebRequest so that I can manually attach the SSL Client cert like so?

webRequest.ClientCertificates.Add(certLoader.Load(@"c:\somecert.pfx"));

Original Question

I am working on a WCF client that needs to interop with a service provided by a third party that's using a Forum Sentry network appliance to secure access. They require SSL with a client cert at the transport level as well as an o:Security element with signature using an cert in the header. I'm able to achieve one or othe other with standard bindings, but I can't seem to get both to happen simultaneosly. Ideally, they want the message signed with a different cert from the SSL client cert but they said we could use the same cert for both the SSL client authentication and to sign the message.

I'm willing to do anything at this point to get this working including using a CustomBinding if necessary.

I can get the SSL part working using the following:

var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var url = "https://blah.com/services/somservice";
EndpointAddress ea = new EndpointAddress(url);
var client = new SoapClient(myBinding, ea);
var certLoader = new CertificateLoader("password");
client.ClientCredentials.ClientCertificate.Certificate = certLoader.Load(@"c:\somecert.pfx");
var resp = client.somemethod(ref profile, new RequestType { version = RequestTypeVersion.Item100 });
like image 999
JohnOpincar Avatar asked Nov 03 '22 23:11

JohnOpincar


1 Answers

please publish a sample working soap (e.g. one the vendor provided). btw there are much more drastic moves than using a custom binding :)

Edit: to use both transport and message security you need custom binding. Google for "wcf binding converter" to do this automatically. In the custom binding instead of http element change it to https and use attribute requirevlientcertificate. Sorry for spelling I'm on mobile

EDIT:

var c = new CustomBinding();            
MessageSecurityVersion version = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
var sec = SecurityBindingElement.CreateCertificateOverTransportBindingElement(version);
c.Elements.Add(sec);
c.Element.Add(new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap11 };)
c.Elements.Add(new HttpsTransportBindingElement() { RequireClientCertificate = true });
like image 50
Yaron Naveh Avatar answered Nov 09 '22 12:11

Yaron Naveh