WebServiceHostFactory and IIS authentication - wcf

I encounter a problem with using the WebServiceHostFactory in IIS.
"IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used."
I wanted to keep both authentication schemes and managed to do so by not using the factory but setting up the endpoint manualy in web.config.
My question is what is WebServiceHostFactory doing to get this result? I was under the impression that WebServiceHostFactory would set the binding to the same webHttpBinding that I used in my config.
Edit:
I have looked at WebServiceHostFactory in reflector and it is not doing anything clever. It is just a simple factory for the WebServiceHost.
Does IIS still use a service host if you set up the endpoint in config? Or is the WebServiceHost setting things up differently.

This is what worked for me. Adding a dummy endpoint early on (before the service host is opened) as shown below seems to have done the trick. (This MSDN article hinted at this http://msdn.microsoft.com/en-us/library/bb412178.aspx.)
public class MyWebServiceHost : WebServiceHost
{
public MyWebServiceHost (Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses)
{
// Inserting this dummy endpoint config seemingly does the trick:
AddServiceEndpoint(typeof(IMyContract), new WebHttpBinding(), string.Empty);
}
protected override void ApplyConfiguration()
{
// Typical programmatic configuration here per:
// http://msdn.microsoft.com/en-us/library/aa395224.aspx
}
}
I'm guessing this prevents WebServiceHost from creating a default endpoint, and thus shutting down a bunch of functionality.

I'm not sure about the WebServiceHostFactory, but it sounds like you're hosting the service inside IIS and it's got more than one authentication method selected. If you've got IIS 5 or 6, try going into IIS and viewing the properties for the website or virtual directory containing your service. Go to the Directory Security tab, click the Edit button under "Anonymous access and authentication control", and then un-tick either "Anonymous access" or "Integrated Windows authentication". I'm not sure about IIS7.

Under IIS7 you might not find where you can manage the Integrated Windows Authentication setting. In order to see the setting in IIS7 management console, you need to follow steps described in the following article: http://msdn.microsoft.com/en-us/library/x8a5axew.aspx (titled as "Error: Debugging Failed Because Integrated Windows Authentication Is Not Enabled", if link is not functional).
Hope it helps.

disable security in web.config-> configuration tag
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding>
<security mode="None">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
then your wcf service doesn't need authentication...

Related

Unable to use NettcpBinding from another computer in my local network

I built a WCF Service in one of my machines of my local network, it has both http and net.tcp (htpp,net.tcp) as enabled protocols in IIS manager.
From another machine a build a client app, and define the endpoints automatically using the Add Service Reference... dialog, I type the service address and when it appears I set the name and click OK. The App.config is updated with two endpoints, one for http (BasicHttpBinding) and the other for net.tcp (NetTcpBinding) as expected.
When running the client app, if I use the BasicHttpBinding:
"using (var proxy = new ProductsServiceClient("BasicHttpBinding_IProductsService"))"
it runs OK, and shows the expected data.
But when I use the NetTcpBinding:
"using (var proxy = new ProductsServiceClient("NetTcpBinding_IProductsService"))"
It throws a SecurityNegotiationException saying that:
"A remote side security requirement was not fulfilled during authentication. Try increasing the ProtectionLevel and/or ImpersonationLevel."
If I do it all in the same machine, I donĀ“t get any exception.
What should I do?
Rafael
By default, the BasicHttpBinding supports no security. So when calling the service from another computer, it will work also.
But by default, NetTcpBinding requires a secure channel. And the default security mode is Transport, so when calling the service from another computer, it will throw a security exception.
The most easy way to solve it is to set the security mode to None as following:
<bindings>
<netTcpBinding>
<binding name="netTcpBindingConfiguration" >
<security mode="None" />
</binding>
</netTcpBinding>
Then we use it in the endpoint
<endpoint address="net.tcp://nelson-laptop:8080/Whatever"
binding="netTcpBinding"
bindingConfiguration="netTcpBindingConfiguration"
contract="ProductsService.IProductsService"
name="NetTcpBinding_IProductsService" />
In Your question you are using the default net.tcp port 808 but have opened port 80 in the firewall. If it is not a typo in the question it could be why it fails.

WCF no SVC file and no Config: Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding

Am using the new VS2010 template for Rest Web Services, which sets up the service without an SVC file and with minimum config, and you set up the route in the global.asax.cs file.
On deploying my WCF Rest Service to test environment where its accessed by https, I get an exception: Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding. Registered base address schemes are [https].
Have found solutions to this on Scott's Blog and Taciturn Discourse
However these solutions are based on having the WCF being configured via the more traditional config route with full specification of endpoint address, binding, contracts.
In the simplified template approach, as we don't setup the endpoint ABC explicitly in config, then how can we fix this issue of the missing base address?
Sorted this out, because using https, need to specify that security is being set at the transport layer. So include this in the system.serviceModel config:
<bindings>
<webHttpBinding>
<binding>
<security mode="Transport" />
</binding>
</webHttpBinding>
</bindings>
My thanks to the two posts below that provided the solution, however found I did not need to put in all their recommendations to get it to work
Configuring WCF 4 with routing (global.asax) for both http & https endpoints
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/1dd991a1-e32f-4035-a406-994729858b40
Cheers, Mickey

Silverlight, WCF service, integrated security AND ssl/https not possible?

I have this setup that works perfectly when using http.
A silverlight 3 client
.net 4 WCF service hosted in IIS with basicHttpBinding and using integrated security on the site
When setting https to required on the website the setup stops working.
Using the wcftestclient on the uri I get the message:
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate,NTLM'. The remote server returned an error: (401) Unauthorized.
Maybe this makes sense because the wcftestclient does not pass credentials?
in the web.config the security mode for the service binding is set is set to 'Transport'.
The silverlight client is created like this:
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
basicHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
var serviceClient = new ImportServiceClient(basicHttpBinding, serviceAddress);
The service address is ofcourse starting with https://
And the silverlight client reports this error:
The provided URI scheme 'https' is invalid; expected 'http'.
Parameter name: via
Remember, switching it back to http (and setting security mode to 'TransportCredentialOnly' makes everything working again.
Is the setup I want even supported? If so, how should it be configured?
Turns out that the above setup does work. The key is
basicHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
In de client code, and
<binding name="silverlightBinding" maxReceivedMessageSize="10485760">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
at the service end.
Somehow I was working with a xap file without the changes in the security mode. As soon as I used the newly compiled xap it started working.

IIS Rest over HTTPS only

I've asked a similar question here:
How to enforce one method in WCF Rest to be called via https, while others can be called over http
And it doesn't look like it is possible on the code side. Is it possible to set up an entire service to be callable over HTTPS only? I've configured a service using the following binding:
<webHttpBinding>
<binding name="webBinding"
maxBufferSize="152428800" maxReceivedMessageSize="152428800"
receiveTimeout="00:10:00">
<readerQuotas maxStringContentLength="152428800"
maxArrayLength="152428800"
maxBytesPerRead="4096"/>
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
But when I try to call a simple service over http, the service returns the result happily, rather than returning some sort of exception. Do I need to configure IIS to only service https requests? Has anyone tried this?
Thanks!
Did you configure IIS to require SSL on your application's folder? (you can set it to allow ssl or make it mandatory)
You can always add an explicit endpoint to your service entry with a fully-qualified https address. Can't remember if IIS hosting always auto-adds the base addresses when you have an explicit address, but even if it does, you can make a simple extension of ServiceHostFactory to "eat" the default base addresses IIS supplies (reference your custom servicehostfactory in the Factory attribute of your .svc file). Then it'll only answer on the exact addresses you supplied in the config.
It's possible via configuration. This Blog Article is not your exact scenario (it's file transfer over https), but it shows sample config and code for configuring and consuming a https web service that should be useful.

Enable SSL for my WCF service

I have a WCF service that uses basicHttpbinding in development.
Now in product we want to use SSL, what changes do I have to make to force SSL connections only?
This page on MSDN explains WCF Binding Security.
http://msdn.microsoft.com/en-us/library/ms729700.aspx
The BasicHttpBinding class is
primarily used to interoperate with
existing Web services, and many of
those services are hosted by Internet
Information Services (IIS).
Consequently, the transport security
for this binding is designed for
seamless interoperation with IIS
sites. This is done by setting the
security mode to Transport and then
setting the client credential type.
The credential type values correspond
to IIS directory security mechanisms.
The following code shows the mode
being set and the credential type set
to Windows. You can use this
configuration when both client and
server are on the same Windows domain.
C#
BasicHttpBinding b = new BasicHttpBinding();
b.Security.Mode = BasicHttpSecurityMode.Transport ;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
Or, in configuration:
<bindings>
<basicHttpBinding>
<binding name="SecurityByTransport">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
To enable ssl, without a login, set clientCredentialType to "None".
Options for security mode are:
None, Transport, Message, TransportWithMessageCredential and TransportCredentialOnly
You can find more details at: http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpsecuritymode.aspx
I just faced the same problem and found this MSDN article:
How to: Configure an IIS-hosted WCF service with SSL
At the end of the article you will find the xml configuration of the WebConfig file.
The solution worked just fine for me. One more thing to say, keep in mind that you need a REAL certificate for your release!
I think that if under your bindings where you have the <Security mode="Transport">, if you would change it to be <security mode="None">, you would be ok.
This is a copy of a code base that I'm working on and I tried that in-code, and it appears to be working.
I get the WSDL at least when I call the service, if that helps at all.
BasicHttpBinding basicBinding = new BasicHttpBinding();
if (RegistryConnectionStringFactory.UseSslForCommunications)
{
basicBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
basicBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
}
else
{
basicBinding.Security.Mode = BasicHttpSecurityMode.None;
basicBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
}