How to secure a Silverlight-Enabled WCF Web Service with SSL? - wcf

How do you secure a Silverlight-Enabled WCF Web Service with SSL? I have tried setting it up similar to a regular WCF service secured by SSL, but it doesn't seem to work. What do you set in the Web.Config, and what do you set in the Silverlight's ServiceReferences.ClientConfig?
I noticed that in the ServiceReferences.ClientConfig file of the Silverlight client app that the "Binding" tag only allows basicHttpBinding and NOT wsHttpBinding. Does this mean that you can not secure a Silverlight-Enabled WCF Service? If so are there better approaches to securing it?

There are three key places that I configure to use https in my own apps.
Web.config
In the behavior tag include this line:
<serviceMetadata httpsGetEnabled="true"/>
For the MEX endpoint, make sure you use the https protocol:
<endpoint address="mex" binding="mexHttpsBinding"
contract="IMetadataExchange" />
Create a custom binding. The important part is the transport security:
<basicHttpBinding>
<binding name="myServicesBinding">
<security mode="Transport"/>
</binding>
</basicHttpBinding>
You can also include the usual authorization stuff:
<authorization>
<allow users="?"/>
<deny users="*"/>
</authorization>
Silverlight
On the Silverlight end, either point the ServiceReference at the now secure service, or set up the connections manually in code. the ServiceReferences.ClientConfig file should have the security stuff in it:
<security mode="Transport"/>
And the code version looks like this:
BasicHttpBinding b = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
There are probably more complex things that can be done, but this should be good enough for most people.

To create Silverlight-Enabled WCF Web Service using SSL you have to do the following steps:
Create standard Silverlight-Enabled WCF Web Service using Visual Studio 2010
Change 3 places of webconfig.xml:
a. In serviceMetadata change httpGetEnabled to httpsGetEnabled like this:
<behaviors >
<serviceBehaviors >
<behavior name="" >
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
b. In binding change httpTransport to httpsTransport:
<bindings>
<customBinding>
<binding name="Project.Web.YourService.customBinding0">
<binaryMessageEncoding/>
<httpsTransport/>
</binding>
</customBinding>
</bindings>
c. in endpoint change binding="mexHttpBinding" to binding="mexHttpsBinding":
<service name="Project.Web.YourService.YourService">
<endpoint address="" binding="customBinding" bindingConfiguration="Project.Web.YourService.customBinding0"
contract="Project.Web.YourService.YourService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
Don't use ServiceReferences.ClientConfig. Create everything in code behind - it's easy to deploy on server:
CustomBinding binding = new CustomBinding(new BinaryMessageEncodingBindingElement(), new HttpsTransportBindingElement());
YourServiceReference.YourServiceClient service = new YourServiceReference.YourServiceClient (binding, new EndpointAddress(new Uri( "https:yourhostname/YourService.svc").AbsoluteUri));
service.YourMethodCompleted += new EventHandler<YourServiceReference.YourMethodCompleted EventArgs>(service_YourMethodCompleted );
service.YourMethodAsync();

in the ServiceReferences.ClientConfig file of
the Silverlight client app that the "Binding" tag only allows
basicHttpBinding and NOT wsHttpBinding.
Does this mean that you can not secure a Silverlight-Enabled
WCF Service?
No, it doesn't mean that. You can have a basicHttpBinding and still assign transport-level security (HTTPS with SSL) to it. That shouldn't be a problem.
Marc
PS: Many one of those links gives you more insight and the proverbial "AHA!" :-)
http://winterdom.com/2007/11/basichttpbindingwithtransportsecurity
http://silverlight.net/forums/p/13275/44170.aspx
http://kevindockx.blogspot.com/2009/02/username-authentication-with.html
http://www.pixel73.com/blog/Default.aspx?g=posts&t=4173
http://community.irritatedvowel.com/blogs/pete_browns_blog/archive/2008/03/19/WCF-Integration-in-Silverlight-2-Beta-1.aspx
Link

WS* is not supported in Silverlight - basically change the URL in the client config to be an https:// url - that's all you can do

Related

How to Resolve EndpointNotFound exception in WCF

I have been trying to resolve a problem that I am having with a WCF service hosted on our cloud platform. Service is written targeting .NET 4.0. I can access the service using both wsHttpBinding and basicHttpBinding over just plain http. However, when I try and access the service over a https end point it consistently gives me an endpoint not found exception which is odd because on the client I add a service reference pointing at the https end point and this should be sufficient to build a compatible proxy?
The web site has a SSL certificate setup which is valid, and the site hosting the service has a binding in IIS that uses this certificate. I can browse to the https URL from within the IIS snap-in and it finds the service with no problems, and I can use the same url from my desktop and get the normal "you have created a service page". IIS has anonymous authentication enabled only.
Here is where I get a bit hazy on what I have to do in terms of the WCF configuration.
In the server web.config I have security mode of Transport and
client credentials of None (Think I need this because of the
anonymous authentication on the host service)
Also in the server web.config I have set up mex end points for each
of the server's end points that are defined.
Is there anything else I need to do here?
On the client side
I have created a basic console app, and create a service
reference pointing at the https url and this is found
In the code I instantiate the proxy and call a method that invokes
the service.
When I run the code I get the end point not found exception.
I have created a really basic ASP.NET web site on my local IIS that hosts a really simple service. I have added a self-signed certificate and in the mmc snap-in I have imported this as a trusted certificate. I have set up a wsHttp end point for both secure and non-secure and when I create a simple client that references the service I get the same problem when using a https end point.So I can replicate the problem I am seeing in the live environment.
The event viewer doesn't shed any light on anything untoward happening.On my various searches I found references to re-registering asp.net and the WCF runtime components. Tried all this to no avail. Getting really stuck. I've included the config from my local asp.net web site, and the client config so people can scan what I have. Any suggestions on what else I could try would be great. I'm hoping I have overlooked something obvious that another pair of eyes with more experience with WCF can spot.
Thanks in advance.
Server config:
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="500" />
</diagnostics>
<services>
<service name="NorthwindServices.ProductService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/NorthwindServices/ProductService/" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="NorthwindServices.IProducts">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="wsHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Secure">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic">
</transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</
==================================================================================
Client config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IProducts">
<security mode="Transport"></security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost/Northwind.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IProducts" contract="ProductProxy.IProducts"
name="WSHttpBinding_IProducts">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
BindingConfiguration is optional since an endpoint is primarily composed of address, binding and contract. If no wsHttpBinding is defined under bindings, the default configuration will be used; if there's one under wsHttpBinding without name or with empty name, the binding configuration will be used if the endpoint does not declare a named one. And you may have multiple named binding configuration under wsHttpBinding, and each endpoint may pick one accordingly. The problems so far according to your config files listed has nothing to do with bindingConfiguration as they all look fine. However, the baseAddress in service side and the client endpoint address do not seem to match, and I presume you are using svc files for service activation. Then you need to make sure the svc files are located in the right place through proper routing. Alternatively you may use config activation without using svc files.

wsHTTPBinding over HTTPS causes Error 400 'Bad Request'

I've been trying to create a simple service to allow messages to be logged onto a remote server via WCF, which all worked fine until I published the service to the live environment, which uses HTTPS.
After some searching, I found that I needed to change my ServiceConfig to account for the different protocol. I used a combination of these two articles:
How to configure WCF services to work through HTTPS without HTTP binding?
WCF Bindings needed for HTTPS
Having made the recommended changes to my config, I seem to be in a state where I can add the live service as a WCF reference in VS2010, but when I use IE to browse to the service or the mex address, I'm consistently receiving an 'HTTP 400 Bad Request' error.
In terms of using the service I can seem to run it successfully but the mex just doesn't want to work through IE.
The Service itself is being hosted on Windows Server 2003 R2 Standard Edition SP2 Running IIS 6.0 with no load balancing.
I'm really at a loss at this point, I've spent 3-4 days messing around with this but I can't seem to make any progress. So any help would be greatly appreciated.
See below the Server service config in question:
<system.serviceModel>
<services>
<service name="mycorp.Callback.SecPayService" behaviorConfiguration="mycorp.Callback.SecPayServiceBehavior">
<endpoint address="https://myserver.co.uk/SecPay/SecPayService.svc"
binding="wsHttpBinding" bindingConfiguration="TransportBinding"
contract="mycorp.Callback.ISecPayService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mycorp.Callback.SecPayServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="TransportBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
If you are hosting your service in IIS then just have the endpoint elements address value to empty string as the address for the endpoint is assigned by IIS

Metadata request requires authentication in WCF even though service description page doesn't

I've set up a WCF service to require NTLM authentication using the following configuration:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="BinarySecurityBinding">
<binaryMessageEncoding/>
<httpTransport authenticationScheme="Ntlm"/>
</binding>
</customBinding>
</bindings>
<services>
<service name="Services.LogisticsServices" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="customBinding" bindingConfiguration="BinarySecurityBinding" contract="Services.ILogisticsServices" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I did this so that the applications that consume the web service are forced to log in because all my service's operations use impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
In IIS 7 I've enabled anonymous and Windows authentication.
When I visit http://test.server/LogisticsServices.svc, which hosts the service described above, I can see the default service description page anonymously. However, when Visual Studio tries to access http://test.server/LogisticsServices.svc/$metadata to generate a client proxy, the server is responding with HTTP code 401 and expecting authentication. Not only would I've expected the metadata to be available anonymously, but additionally, the server is not accepting the credentials I am giving it (even though, I know for a fact that they are correct).
Testing different configuration, I tried removing the authenticationScheme from my binding's transport, just to be able to generate the client proxy, but that results in an exception because the service's operations require impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
What am I missing in my service's configuration that would make the service's metadata available anonymously? I'm also open to suggestions if I'm approaching the whole thing wrong.
here is a similar discussion:
Getting an Security setting exception while accessing a WCF service
One way around this is not to use the autogenerated proxies.
In cases where we have control over both the server and the client we have found that it is much more productive to avoid using the autgenerated proxies.
A screencast of how to do this can be found here: http://www.dnrtv.com/default.aspx?showNum=122
You could try imperative instead of declarative model, see: http://msdn.microsoft.com/en-us/library/ms730088.aspx

Wcf Http and Https

Help please!!
I had the following set up working perfectly:-
WCF Service Library hosted in web site on local IIS 7
Silverlight Application on a web site on local IIS 7 using above services
The solution I am writing is for intranet and not internet use, however I have been told by my bosses that it needs to be over Https. I am using Windows Authentication.
Below is a chunk of the config file for one of the service endpoints (changed to remove company info etc):-
<services>
<service behaviorConfiguration="stdHttpBehavior" name="WcfServiceLibrary.StaticDataService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="windowsHttpBinding"
name="StaticDataService" contract="WcfServiceLibrary.ServiceContracts.IStaticDataService" />
<endpoint address="mex" binding="mexHttpBinding" name="" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/WcfServiceLibrary/StaticDataService/" />
</baseAddresses>
</host>
</service>
<behaviors>
<serviceBehaviors>
<behavior name="stdHttpBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
</behaviors>
To experiment with Https I created a 'Self-Signed Certificate'. I then added https to the Default Web Site bindings and changed the two web sites to require SSL and also changed the relvant URIs in the config files. I managed to get this to work but now I want to go back to standard Http and finish the project in that mode as it was easier to work with. I changed all the settings back (and I have checked these extremely carefully).
Now I get this error if I try to downoad the Service definition in the Silverlight project: -
'Could not find a base address that matches scheme https for the endpoint with binding BasicHttpBinding. Registered base address schemes are [http].'
If I put back the certificate and binding in IIS. The Service definition appears to download OK, however it references an https URI and therefore none of the actual service calls work as they are http adresses!
I tried adding a new web site to host the service but got the same errors.
I have been trying to solve this for the last couple of days but cannot find an answer. It seems as though there is a hidden reference somewhere and not in my project as it continued with a new web site added to IIS.
To use SSL over HTTP under Basic HTTP binding, you need to switch your endpoint to use Transport-level security. In your case you will also want to indicate the client credential type:
<bindings>
<basicHttpBinding>
<binding name="windowsHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
<message />
</security>
</binding>
</basicHttpBinding>
</bindings>
It may seem obvious, but did you change the security mode on the windowsHttpBinding binding configuration to BasicHttpSecurityMode.None?
<bindings>
<basicHttpBinding>
<binding name="windowsHttpBinding">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
Related resources:
Transport Security Overview
BasicHttpSecurityMode Enumeration

SSL WCFs with custom binding

Has anyone ever tried to use custom binding with SSL in a WCF web service? I've seen a number of examples on how to do this with basicHttpBinding and wsHttpBinding but the equivalent always fails for customBinding. Specifically what I'm currently working with (the most successful configuration yet) looks something like this:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="binaryHttps">
<binaryMessageEncoding />
<httpsTransport />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyService">
<host>
<baseAddresses>
<add baseAddress="https://(myserver)/"/>
</baseAddresses>
</host>
<endpoint address=""
binding="customBinding" bindingConfiguration="binaryHttps"
contract="MyService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
This actually allows us to access the service from the web, get it's WSDL and add a service reference inside visual studio alright, but when we actually try and use it live in our silverlight-3 application, it just sits there indefinitely waiting for a response and never times out. It actually ends up giving me low memory problems after a while on my machine (with 6GB of memory). The odd thing is that all this worked (and still does) perfectly in the development environment (using strictly the VS application hosts), it wasn't until we tried to deploy it to an actual server with a real SSL certificate that all these issues popped up.
I've searched fairly exhaustively for a solution to this problem but have so far not found anything and have tried just about everything - Is there anyone out there that's encountered this before and got around it?
So it turns out the problem wasn't with our web.config at all, it had to do with an issue with IIS 7 and Wildcard SSL certificates.
Namely, IIS 7 doesn't allow you to specify the hostname when binding an IP to an SSL connection and certificate. I'd guess that this is because it expects a non-wildcard SSL certificate that it can extract the explicit hostname from. What we ended up having to do was to go into the applicationHost.config file in {WindowsDir}\{System32}\{Inetsrv}\{config} and find the entry with our web service's bound IP address and change it explicitly to (ip):(hostname). It was then even displayed properly in the IIS config GUI.
After doing this we were to completely turn off all but SSL channels on all our servers and everything worked beautifully.
Thank god that's over!
AFAIK, using SSL has performance problem. We are using WCF behiovr to do the authentication. The way that we are using is that Silverlight => ASP.NET => WCF. We configured the Endpoint behivor in both Silverlight and WCF. Whenever we call the service, we passed the token for authentication.
Are you saying that you can use custom binding in ClientConfig of Silverlight?