I've got a service that can communicate with a GUI via WCF.
In the app.config I currently have this security configuration:
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
If the GUI is installed in the same PC of the service, I would like to establish a communication without being connected to the network. I can do it only if I modify the app.config setting:
<security mode="None" />
Is there any "universal" solution that keeps the security but works "offline"?
Even though you have your security set to "message", I suspect you actually have no security (encryption) at all. "Message" security means you're using certificates, on both the host and client, to encrypt the XML located inside your transmission. So if you're not passing XML, or if you're not using common SSL certs stored on both the host and client (even if it's the same machine), you're not really encrypting anything. (It's easy to verify this using a packet sniffer or program like Fiddler)
The only other option for security (encryption) is transport, which is SSL used the old-fashion way. But why would you need to encrypt information traveling between points "A" and "B" on the same machine? I wouldn't even worry about it over an internal network, as long as your network is secure.
Encryption is needed when you traverse publc networks like the WWW, where bad people, or the NSA, is snooping for useful information.
Related
I have a WCF service which the security mode has been set to "Transport".
Below is my service configuration:
<bindings>
<netTcpBinding>
<binding name="tcpConSecure" >
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
</bindings>
When I use VisualStudio "Edit WCF configuration" tool to open my configuration, in security tab, it will display like this:
Question:
Does the setting in MessageSecurity properties area still work when I set mode to Transport? I ask this question because I didn't set message security related properties in config file.
When I set Security Mode to "Transport" and client credential type to "Windows", will the transfer message between server/client be encrypted? By which algorithm?
From this link, the messages are secured at the transport level by windows security. What does Windows Security mean?
For the first question, if the mode is set to "Transfer", the settings in the MessageSecurity properties area will be invalid. Securing a service with both transport and message credentials uses the best of both Transport and Message security modes in Windows Communication Foundation (WCF). In sum, transport-layer security provides integrity and confidentiality, while message-layer security provides a variety of credentials that are not possible with strict transport security mechanisms. For more information about TransportWithMessageCredential, you can refer to this link.
If the Transport mode is used, the main mechanism used to protect the transmission is the Secure Sockets Layer (SSL) based on HTTP, usually called HTTPS. So if we use Transport mode, we need to bind a certificate to the service. For more information about Transport Security, you can refer to this link.
Some clients need to be able to connect to our WCF SOAP services using Basic authentication, while others need to use Windows authentication. We normally host our services in IIS, although we do provide a less-developed Windows Service hosting option.
It's my understanding that it is not possible to configure one endpoint to support both Basic and Windows authentication. So we have two endpoints per service.
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicBinding" contract="SomeContract" bindingNamespace="http://www.somewhere.com/Something" />
<endpoint address="win" binding="basicHttpBinding" bindingConfiguration="WindowsBinding" contract="SomeContract" bindingNamespace="http://www.somewhere.com/Something" />
...
<bindings>
<basicHttpBinding>
<binding name="BasicBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
<binding name="WindowsBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
These are in the same Web Application in IIS. That Web Application has both Basic and Windows authentication enabled (else one of the above bindings wouldn't work).
When a client uses the Windows-authenticated endpoint (with "win" on the end of URL), this typically works fine. When the initial request doesn't contain any authentication information, a negotiation takes place between the client and IIS, they settle on Windows authentication and all goes well.
When a client uses the Basic-authenticated endpoint (without "win" on the end of URL), this works if they include the Authorization HTTP header with the correct encoded credentials in it. However, if they do not include any authentication information in the initial request, the negotiation ends up choosing Windows authentication. This gets the request past IIS security, but WCF then refuses the request, because it's going to a Basic-authenticated endpoint.
I am rather hazy on exactly what's happening in the negotiation. But it seems to me that IIS offers all authentication methods enabled for the Web Application (i.e. Basic and Windows), even though the particular WCF endpoint URL for the request only supports Basic.
I would like to know if there is anything we can do in IIS to make the negotiation come up with the right answer: that is, if the request is to a Basic-authenticated endpoint, tell the client to use Basic. Of course, we still want the negotiation to end up choosing Windows, when the request went to the Windows-authenticated endpoint.
If there isn't, then do you think we would be better off concentrating on our Windows Service-hosted version of the services? Or would that have similar problems somehow?
Final note: we do use Basic with HTTP for some internal uses, but we do know that this is an insecure combination. So we typically turn on HTTPS for production use; I've left that out here, for simplicity.
Yes, clientCredentialType="InheritedFromHost" solves the problem for me. This, new in .Net 4.5, means that one can now use the same endpoint URL for more than one authentication type. IIS settings control what authentication is allowed, meaning no longer possible to get IIS and WCF settings in conflict.
We have a WCF Data Service which is self-hosted under a Windows service (not using IIS) which we are currently working to secure using SSL and Windows Authentication.
After some time playing around with netsh and server certificates, we now have the service secured with SSL and we have also enabled Windows Authentication on the webHttpBinding in our app.config - however we are now seeing some strange behaviour when attempting to authenticate certain users - some can log in fine, others have their credentials rejected and are prompted with HTTP 400 errors.
After some testing and digging around it would appear that we might be running into this problem, where the authentication header used by Kerberos may be greater than the maximum permitted header length (which I believe is 16k) for certain users - and although there is a documented workaround for IIS, there does not appear to be an equivalent setting we can use for a self-hosted service, or in our app.config - unless I'm missing something? We tried setting the maxReceivedMessageSize and maxBufferSize fields to their maximum values to see if that would make any difference, but apparently not.
Binding config:
<webHttpBinding>
<binding name="DataServicesBinding"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</webHttpBinding>
We've managed to work around this issue temporarily by setting the clientCredentialType in our binding to use Ntlm instead, but we'd like to get Kerberos working if possible for obvious reasons.
So, as it turns out, this was caused by our service not being configured with a SPN (Service Principal Name). This can be done using the setspn tool with Windows Server. (See this MSDN article for more information.)
Once the SPN was applied, Kerberos authentication started to work as expected.
Use wireshark to see what the client sends. Make sure that this input is correct and then come back.
I want to retrieve the username and password of user that requires the service operation. For this i need to specify the following configuration:
<binding name="NewBinding0">
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
Now it requires the x509 certificate. Can i disable it, or modify the security mode or message credentialType, but to provide the same functionality?
When you specify message security it always expects service certificate. The reason is that user name and password should be send over secured channel otherwise password is send as a plain text and everybody on the network can see that.
All default bindings will allow you sending user name and password only when you are using HTTPS (security mode set to TransportWithMessageCredential - it also requires certificate) or if you are using WS-Security where service certificate is needed (security mode set to Message).
In WCF 4 (and with special KB patch in earlier versions) you can create custom binding where user name and password can be send over unsecured channel but it is almost the same as no security. It should be used only if your channel is secured with some another infrastructure like VPN.
I keep getting the following error "Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http]." This started because I went to Basic Transport Authentication by adding:
<webHttpBinding>
<binding name="secureBasic">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</webHttpBinding>
After googling the common fix seemed to be the following code, but I had no success with it:
<baseAddressPrefixFilters>
<add prefix="http://mywebsiteurl"/>
</baseAddressPrefixFilters>
Still, nothing works. All I want is to use basic http authentication on a non-https connection. I have configured absolutely nothing and it appears by default WCF wants to force a HTTPS connetion. Anyone run into this?
If you tell WCF to use transport security mode, you must use a transport protocol that supports secure communication. HTTP doesn't support secure communication because it's a plaintext protocol (anyone that intercepts your communication can simply read what is being transmitted). HTTPS does support secure communication so your only option for a webHttpBinding with transport security is to use HTTPS (which you can configure in IIS).
Here is a blog post describing your error and how to solve it using TransportCredentialOnly. It's about basicHttpBinding but the same holds for your webHttpBinding.
If you want only transport level authentication (= Basic authentication) but you don't want transport level secure communication (= HTTPS) you have to set security mode to TransportCredentialOnly.