← Back to overview
September 3, 2009 · Windows Communication Foundation

WCF and fixing client/host time issues (MaxClockSkew) quickly

I have noticed that some of my WCF clients suddenly had issues connecting. These were the exceptions:

The security timestamp is stale because its expiration time is in the past. An error occurred when verifying security for the message

The problem was that the server time had a difference of +/- 10 min. with the clients that had problems. Since these clients are not part of the domain at all we had a problem, since WCF only allows a 5 min. difference.

This could "easely" be solved with:

But this is only supported by custom bindings. Custom binding doesn’t support properties like readerQuotas … so this creates a new problem. You could for example add tcpTransport in your custom binding but here again not all the properties are available. And I’m actually not a fan of having to rewrite all my bindings.

That’s why I liked the following solution (note, this is only when you host your service in an application/service):

ServiceHost service = new ServiceHost(typeof(Calculator));  
Binding currentBinding = service.Description.Endpoints[0].Binding;  

With this code we get our current binding (presuming the endpoints and bindings are in the App.config).
Then we just have to update the current binding with a custom binding:

// Set the maximum difference in minutes 
int maxDifference = 300;

// Create a custom binding based on an existing binding
CustomBinding myCustomBinding = new CustomBinding(currentBinding);

// Set the maxClockSkew
var security = myCustomBinding.Elements.Find<SymmetricSecurityBindingElement>();  
security.LocalClientSettings.MaxClockSkew = TimeSpan.FromMinutes(maxDifference);  
security.LocalServiceSettings.MaxClockSkew = TimeSpan.FromMinutes(maxDifference);

// Set the maxClockSkew
var secureTokenParams = (SecureConversationSecurityTokenParameters)security.ProtectionTokenParameters;  
var bootstrap = secureTokenParams.BootstrapSecurityBindingElement;  
bootstrap.LocalClientSettings.MaxClockSkew = TimeSpan.FromMinutes(maxDifference);  
bootstrap.LocalServiceSettings.MaxClockSkew = TimeSpan.FromMinutes(maxDifference);

// Update the binding of the endpoint
service.Description.Endpoints[0].Binding = myCustomBinding;  

The only thing we had to do is create a custom binding based on an existing binding.
After that we adapted the maxClockSkew on the required objects and then injected the new binding back to the endpoint.

If you have multiple endpoints you should apply this on all your endpoints.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket
Comments powered by Disqus