Fixing WCF IOrganizationService client/host MaxClockSkew security issues

Recently I stumbled upon an issue where WCF clients started to experience connectivity issues with our WCF service calls to CRM, with MaxClockSkew timings.

MessageSecurityException: The security timestamp is invalid because its creation time ('xx') is in the future. Current time is 'xx' and allowed clock skew is '00:05:00'. An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when verifying security for the message.

The problem here was that the clocks between the clients and the service were out of Sync, with approx. 10-15 minutes.
The default however, for the receiver to accept message with a send-time is just up to 5 minutes later or earlier.
Messages that do not pass the send-time test get rejected immediately. So this had to be fixed by allowing a larger timeframe between the two parties communicating, by setting;

  • LocalClientSettings.MaxClockSkew
  • LocalServiceSettings.MaxClockSkew

Since we were creating the service proxy programmaticely (for Dynamics CRM), without any configuration from file, we had to fix this from code;

var serviceProxy = new OrganizationServiceProxy(organizationUri, null, credentials, null);
serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());

// Find the Security binding element and set the MaxClockSkew 
var customBinding = new CustomBinding(serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Binding);
var security = customBinding.Elements.Find<TransportSecurityBindingElement>();
security.LocalClientSettings.MaxClockSkew = TimeSpan.FromMinutes(60);
security.LocalServiceSettings.MaxClockSkew = TimeSpan.FromMinutes(60);
serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Binding = customBinding;

var organizationService = (IOrganizationService)serviceProxy;

Which comes down to creating a new Custom binding, based on the existing binding. Find the security element to update the MaxClockSkew and inject the new binding to be used by the endpoint.

Note that if you have multiple endpoints, this needs to be applied for each of them.