Enable WCF replay detection cache with certificate based message security - wcf

I have a WCF service that has the following requirements:
Sent over SSL (HTTPS Transport)
Reliable Messaging On
WS-* message security using a X.509 certificate.
Replay Detection On
Here is the binding that I have:
<customBinding>
<binding name="replayDetectionBinding">
<reliableSession />
<security authenticationMode="SecureConversation">
<secureConversationBootstrap authenticationMode="CertificateOverTransport"
protectTokens="true">
<issuedTokenParameters keyType="AsymmetricKey" />
</secureConversationBootstrap>
<localServiceSettings maxClockSkew="00:01:00"
replayWindow="00:01:00" />
</security>
<textMessageEncoding />
<httpsTransport maxReceivedMessageSize="5242880" maxBufferSize="5242880" />
</binding>
</customBinding>
The service is hosted in IIS and I have a test client to make a request to the service. I have Fiddler up and running to catch all messages coming to and from the test client and the WCF service.
Everything is working, including the replay detection outside of the replay window. However, what I need is to have the replay detection use the nonce cache so that an identical message is rejected no matter what (as long as that message signature is in the nonce cache). This part is not happening.
I send a message using the test client, it is received by the WCF service and a response is returned, I do not close the connection. I then use Fiddler to reissue/replay the message that was sent. In this case, it is accepted by fiddler - even if I issue it from another machine.
I've done so much searching and have read just about everything I can find, but cannot get this to work.
Does anyone know how to enable the nonce cache in this case or do you have to code your own?

Related

How to expose WCF service with Basic and Windows authentication options, so Negotiation works

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.

WCF over MSMQ, 403 Service unavailable

I setup a WCF service to work over HTTP and MSMQ. It kind of works. The HTTP protocol works 100%. The problem is with net.msmq. When I check the queue, the messages have gone down by 1 which I assume means it's being processed. But at the same time, the service is no longer available. I receive a 403 service unavailable error from IIS. When I purge the queue and reset the site, the service is available again.
Message queue has full permissions for everyone and the service doesn't do anything (seriously, it's just a stub method) so it isn't a code problem.
The contract is marked as one way and the action is *.
Messages are going into the queue (sending 10 at a time) and at least 1 message is getting pulled (count goes down to 9).
The net.msmq listener service is running.
How can I fix this problem?
I had the same problem, because I forgot to specify the bindingConfiguration. I had the binding setup like
<bindings>
<netMsmqBinding>
<binding name="Msmq" exactlyOnce="true" >
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
Once I realized the bindingConfiguration was missing from my endpoint, I added it in, and it started working correctly.
<endpoint address ="net.msmq://localhost/private/MyQueue.svc"
binding="netMsmqBinding"
contract="IService" bindingConfiguration="Msmq">

WCF using Transport always attempts to use HTTPS when I don't want it to

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.

Which authentication mode of basichhtpbinding can be used to secure a WCF Service using Streaming?

Details about my service:
A file upload service
Transfermode is set to stream
Service is hosted in IIS 7.
I need to provide secuirty to my service. I have tried with ntlm and windows secuirty.I was getting the following error when i am trying to secure my service
"HTTP request streaming cannot be used in conjunction with HTTP authentication. Either disable request streaming or specify anonymous HTTP authentication."
I have found a description stating that:
Description:
You can't do transport auth. with streaming. If you have to use HTTP request streaming, you'll have to run without security.
So i wish to know how can i secure my service? Which secuirty mode can i use with basichttpbinding?Can anyone pls help me on this?
You can try using TransportWithMessageCredential:
<bindings>
<basicHttpBinding>
<binding name="securedStream" transferMode="streamed">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
This will pass credentials in SOAP header. Now you must either pass user's name and password - default validation is against Windows accounts but you can also use Membership provider or custom password validator.
If you really want NTLM or Windows then it means you are running both client and server in the same network / domain. In such case use Net.tcp instead.

WCF: The request for security token could not be satisfied because authentication failed

I have written a very simple WCF Service that sends and receives messages. I have tested the app through the VS 2008 default web server host and everything works fine. But when I deploy the WCF service to another computer's IIS I receive the following error:
"The request for security token could not be satisfied because authentication failed."
How can I set the authentication type to use my custom username and password in config file?
If it is not possible, please tell me how I can set its windows credentials because the 2 computers that I'm using, don't share the same users.
You need to turn off security for the binding. Otherwise, I believe that, by default, the wsHttpBinding will try to negotiate a Security Context Token (SCT).
So, modify the endpoint definition to point to a binding configuration section. Here's an example:
<endpoint address=""
binding="wsHttpBinding"
contract="HelloWorldService.IService1"
bindingConfiguration="TheBindingConfig">
And then add something like the following binding configuration right after the <services> section in the web.config's <system.serviceModel> section.
<bindings>
<wsHttpBinding>
<binding name="TheBindingConfig">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
Setting security to "None" is the key.
Hope this helped!
The above helped me - but what is not immediately obvious is how to add to the service end (its clear once you've done it what's needed, but not until you've done so). The reason its not entirely obvious is because there isn't a bindings section by default whereas there is liable to be one in the client.
So, just to be very clear - at the service end, add the bindings section (as detailed above) and then to the appropriate endpoint add the bindingConfiguration="TheBindingConfig" attribute. Obvious once you've done it once...
You don't actually need to turn off security and in some cases you shouldn't. Within a bindingConfiguration, you can specify message level security that does not establish a security context as follows:
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="false" />
</security>
Note the establishSecurityContext attribute. Both the client and service should have a security configuration with establishSecurityContext set to the same value. A value of true also works fine but false is recommended in an environment where the servers are load balanced.
Be sure to set this bindingConfiguration (specifying security mode 'none') on both client and server or else you will get this message - which is quite a red herring as far as debugging the problem.
The message could not be processed.
This is most likely because the action
'http://tempuri.org/IInterfaceName/OperationName'
is incorrect or because the message
contains an invalid or expired
security context token or because
there is a mismatch between bindings.
The security context token would be
invalid if the service aborted the
channel due to inactivity. To prevent
the service from aborting idle
sessions prematurely increase the
Receive timeout on the service
endpoint's binding.
If you are in debug mode then set the debug attribute as
<serviceDebug includeExceptionDetailInFaults="true"/>
by default it sets as false ..so while you go for debugging it throws that exception .
hope it helps .