Tuesday, April 14, 2009

Configuring WCF with BasicHttpBinding and SSL

Despite a variety of posts on this topic, I had to go through a bunch of articles just to get what seemed to be a simple task.

I started with this post How to setup a WCF service using basic Http bindings with SSL transport level security. The post gives a good explanation of how to get a ssl certificate and set up IIS to use the certificate. In my case, I just wanted to use SSL and not credentials. So I modified the web.config like this:

<bindings>
<basicHttpBinding>
<binding name="basicHttps">
<security mode="Transport">
<transport clientCredentialType="None" />
<message />
</security>
</binding>
</basicHttpBinding>
</bindings>

Then I added a bindingConfiguration to the service configuration:

<service name="PartnerAPI.Service" behaviorConfiguration="PartnerAPI.ServiceBehavior">
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttps" contract="PartnerAPI.IService" >

Now after doing that, I went to my service at https://localhost/PartnerAPI/Service.svc?wsdl which gave me the error: "Could not find a base address that matches scheme http for the endpoint with binding MexHttpBinding. Registered base address schemes are [https]."

I also needed to tell the MexHttpBinding to use SSL. Fortunetly, .Net gives us SSL for MexHttpBindings so we don't need to configure it. Set the binding attribute to mexHttpsBinding instead of mexHttpBinding.

<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>

Since I had httpGet enabled for Metadata, we also need to set it to use SSL. Instead of setting httpGetEnabled="true", I set httpsGetEnabled="true".

<serviceMetadata httpsGetEnabled="true"/>

Finally, the wsdl displays correctly with https and I get a 403 error with http. I change the url in for my test client but when running unit tests, I get this exception "System.ServiceModel.Security.SecurityNegotiationException: Could not establish trust relationship for the SSL/TLS secure channel with authority."

This is happening because in dev, my SSL certificate is invalid. I need to override validation of the certificate in my test client.

//force acceptance of invalid ssl certificates (for dev)
ServicePointManager.ServerCertificateValidationCallback += ((sender, certificate, chain, sslPolicyErrors) => true);
//create the client
client = new PartnerAPITest.TutorAccountAPI.ServiceClient();

Note: I'm using an anonymous function that always returns true. You could also create a custom class that inherits ICertificatePolicy. Both approachs are explained here.

3 comments:

Andy said...

Thanks, this worked perfectly.

becca said...

Glad to help!

jbarach said...

Dude.. you rock. Thank you for the walk thru.