How to make WCF service server-client time difference independent?

10,039

There can be multiple reasons for this error, the common one is related to server not authenticating client for variosu reasons (maybe not on the same domain). To determine the exact reasons turn on wcf trace and see what errors it shows in red. What you're looking for is the inenr exception which is a little hidden in the trace UI, it is in the right side in the middle down the tree.

Here is how to set a clock skew:

<security authenticationMode="...">
           <localClientSettings maxClockSkew="00:07:00" />
           <localServiceSettings maxClockSkew="00:07:00" />
           <secureConversationBootstrap>
              <localClientSettings maxClockSkew="00:30:00" />
              <localServiceSettings maxClockSkew="00:30:00" />
           </secureConversationBootstrap>
</security>

Note skew can only be defined on a custom binding. Since you use WSHttpBinding you need to convert it to a custom binding which can be easily be done online via WCF binding converter.

Share:
10,039
Aishwarya Shiva
Author by

Aishwarya Shiva

With over 10 years of experience providing thorough and skillful advice in software development, digital marketing, PC troubleshooting and other tech related issues to both individuals and businesses. Use this VIP link and give me a call for free .NET, C#, ASP.NET, MVC, JAVA, PHP, WCF, WPF etc. consultation: https://clarity.fm/aishwaryashiva/early638

Updated on June 05, 2022

Comments

  • Aishwarya Shiva
    Aishwarya Shiva almost 2 years

    While accessing WCF service from a test client, I am getting following exception:

    System.ServiceModel.Security.MessageSecurityException: 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.
       --- End of inner exception stack trace ---
    

    I searched on internet the root cause of this problem. I found that this is mostly caused due to client-server time difference. But I was unable to find the correct solution to it. Following is my server side configuration:

     <system.serviceModel>
        <bindings>
          <wsHttpBinding>
            <binding name="RequestUserName">
                <security mode="Message">
                  <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" />
    
                </security>
            </binding>
          </wsHttpBinding>
    
        </bindings>
        <services>
          <service name="WCFService.Service1" behaviorConfiguration="WCFService.Service1Behavior">
            <!-- Service Endpoints -->
            <endpoint address="http://subdomain.domain.com/service1.svc" binding="wsHttpBinding" contract="WCFService.IService1" bindingName="RequestUserName">
    
    
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="WCFService.Service1Behavior">
              <!-- To avoid disclosing metadata information, set the value below to false before deployment -->
              <serviceMetadata httpGetEnabled="false" />
    
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false" />
    
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment>
          <baseAddressPrefixFilters>
            <add prefix="http://subdomain.domain.com/"/>
          </baseAddressPrefixFilters>
        </serviceHostingEnvironment>
    

    and Client Side Configuration:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.serviceModel>
            <bindings>
                <wsHttpBinding>
                    <binding name="RequestUserName_IService1" />
                </wsHttpBinding>
            </bindings>
            <client>
                <endpoint address="http://subdomain.domain.com/service1.svc" binding="wsHttpBinding"
                    bindingConfiguration="RequestUserName_IService1" contract="ServiceReference1.IService1"
                    name="RequestUserName_IService1">
                    <identity>
                        <userPrincipalName value="DOMAIN\subdomaincom_web" />
                    </identity>
                </endpoint>
            </client>
        </system.serviceModel>
    </configuration>
    

    Anyone please help me find the solution to this problem.

    UPDATE: When I traced the exception, the inner exception is showing this The security timestamp is stale because its expiration time ('2013-08-21T11:17:39.482Z') is in the past. Current time is '2013-08-21T12:31:31.897Z' and allowed clock skew is '00:05:00'.

    My server uses UTC format and my client is a general purpose application that can be downloaded from any country.

    UPDATE 2: Config after answer:

    <system.serviceModel>
        <bindings>
          <customBinding>
            <binding name="Wrabind">
              <transactionFlow />
              <security authenticationMode="SecureConversation" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
                <localClientSettings maxClockSkew="00:07:00" />
                <localServiceSettings maxClockSkew="00:07:00" />
                <secureConversationBootstrap messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" />
                    <localClientSettings maxClockSkew="00:30:00" />
                    <localServiceSettings maxClockSkew="00:30:00" />
              </security>
              <textMessageEncoding />
              <httpTransport />
            </binding>
          </customBinding>
        </bindings>
        <!-- change -->
        <services>
          <service name="WCFService.Service1" behaviorConfiguration="WCFService.Service1Behavior">
            <!-- Service Endpoints -->
            <endpoint address="http://subdomain.domain.com/service1.svc" binding="customBinding" contract="WCFService.IService1" bindingName="Wrabind">
              <!-- 
                  Upon deployment, the following identity element should be removed or replaced to reflect the 
                  identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
                  automatically.
              -->
    
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="WCFService.Service1Behavior">
              <!-- To avoid disclosing metadata information, set the value below to false before deployment -->
              <serviceMetadata httpGetEnabled="false" />
              <!-- change -->
              <!--<serviceCredentials>
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFService.Authentication.DistributorValidator, WrangleCoreService"/>
                <serviceCertificate findValue="WCFService" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
              </serviceCredentials>-->
              <!-- change -->
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false" />
    
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment>
          <baseAddressPrefixFilters>
            <add prefix="http://subdomain.domain.com/"/>
          </baseAddressPrefixFilters>
        </serviceHostingEnvironment>
        <!--<standardEndpoints>
          <webHttpEndpoint>
            <standardEndpoint name="" helpEnabled="true"
              automaticFormatSelectionEnabled="true"/>
          </webHttpEndpoint>
        </standardEndpoints>-->
    
      </system.serviceModel>
    
  • Aishwarya Shiva
    Aishwarya Shiva over 10 years
    This is what I am getting from inner exception: The security timestamp is stale because its expiration time ('2013-08-21T11:17:39.482Z') is in the past. Current time is '2013-08-21T12:31:31.897Z' and allowed clock skew is '00:05:00'.</
  • Yaron Naveh
    Yaron Naveh over 10 years
    check that the clocks in both machines are accurate (up to 5 min difference is ok), including daylight saving time setting. just for the purpose of testing sync them in terms of hour, daylight, and time zone and see if that helps.
  • Aishwarya Shiva
    Aishwarya Shiva over 10 years
    I changed client time and it worked. But as I said in my question update that my client is a downloadable application and my server uses UTC (I can't change server time, its been used by other types of clients). So my client can use any time zone. This error will re-appear in those clients that have more time zone difference from server. So is there any general solution to this? So that my client application can be used from any part of the world?
  • Yaron Naveh
    Yaron Naveh over 10 years
    the problem is not related to time zones - change to different time zones and see (of course make sure they both refer to the same UTC hour, e.g. if NY is 7 so LA should be 10). The problem is essentially if there are more than a few minutes differences in clocks (or in a private case of daylight saving time). You can increase the clock skew to ensure you can handle any difference in clocks you consider valid. see my edit in a moment...
  • Aishwarya Shiva
    Aishwarya Shiva over 10 years
    Thanks for this. But when I pasted your code and tried to update client reference, it says that The element <localClientSettings> may only appear once in this section
  • Yaron Naveh
    Yaron Naveh over 10 years
    if you still have a problem with it publish your full config
  • Yaron Naveh
    Yaron Naveh over 10 years
    on the client config use only localClientSettings and on the server only localServerSettings
  • Aishwarya Shiva
    Aishwarya Shiva over 10 years
    No I mean you wrote two times the <localClientSettings> and <localServiceSettings>, one before <secureConvertionBootstrap> and one inside it. So that's why its saying The element <localClientSettings> may only appear once?
  • Yaron Naveh
    Yaron Naveh over 10 years
    not sure. maybe it sees the localServerConfig as the same type as localClientConfig. Otherwise use the WCF config editor UI to create the setting - it will create a valid setting
  • Aishwarya Shiva
    Aishwarya Shiva over 10 years
    Thanks. I will try to research on it more. :)