Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The request for security token could not be satisfied because authentication failed when turning off TLS 1.0

Tags:

c#

.net

wcf

So I am attempting to turn off TLS 1.0 and 1.1 on my server. When I switch off TLS 1.0 I get the following error in my application:

System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---> System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
   at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
   at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)

When TLS 1.0 is enabled everything works fine.

Now the code calling the service is specifying TLS 1.2 using the ServicePointManager with the following code: ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

The service on the other end is running .Net 4.6.2 and does not specify a TLS protocol using the ServicePointManager, so from what I have read it will automatically detect which TLS protocol is required at runtime in this version of the .net framework.

The Web.config for the WCF services are the following in regards to the bindings

Calling Config:

<basicHttpBinding>
    <binding name="MyBinding" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="00:02:00" sendTimeout="00:02:00"/>
</basicHttpBinding>
<netTcpBinding>
    <binding name="CrossDomainBinding">
          <security mode="Message">
              <message clientCredentialType="Certificate"/>
          </security>
    </binding>
</netTcpBinding>
<client>
    <endpoint address="net.tcp://MyService.svc"
    binding="netTcpBinding" bindingConfiguration="CrossDomainBinding" behaviorConfiguration="CrossDomainBehavior"
    contract="MyContract" name="MyBinding">
        <identity>
            <certificate encodedValue="CERTIFICATEENCODEDVALUE" />
        </identity>
    </endpoint>
</client>

Service Config:

<bindings>
    <netTcpBinding>
        <binding>
            <security mode="Message">
                <message clientCredentialType="Certificate"/>
            </security>
        </binding>
    </netTcpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="MyBehaviour">
      <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
        <serviceCertificate findValue="MyCertificate" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

I cannot for the life of me work out what the issue is here.

Does anyone have any idea why when turning off TLS 1.0 this does not work?

like image 673
Jamie Rees Avatar asked Nov 22 '17 15:11

Jamie Rees


1 Answers

As you know, the problem is SSL3 and TLS1.0 are vulnerable to POODLE attack, and other threads. So, migrating to .NET 4.5, which supports TLS 1.1 and TLS 1.2, or above is a good idea.

Basically, the client will negotiate with the server and take the highest protocol that server provides. As long as server provides TLS 1.1 or TLS 1.2, the client will use theTLS 1.1 or 1.2.

If your app is .NET 4.0, you can still use TLS 1.2 by installing .NET 4.5 on your server. Your app will not have to be retargeted to .NET 4.5. You can forcefully change the protocol in .NET 4.0 app as shown below (and already do):

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;//SecurityProtocolType.Tls1.2;

One caveat is simply upgrading to .NET 4.5 does not automatically solve the problem. That is because the default protocol is SSL3/TLS1.0 in .NET 4.0/4.5. So in order to use TLS 1.2 or TLS 1.1 in .NET 4.5+, you will need to set SecurityProtocol (using the SslProtocols Enumeration or the corresponding integer values) before any WebRequest calls (actually, this has to be done only once per AppDomain. But it does not hurt to set it again).

In the first place, TLS is terminated in Windows by a component called SChannel. The supported ciphers are dependent on the version of SChannel, which is dependent on the OS, NOT on the .NET version; e.g. Windows XP only supports up to TLS 1.0. Ref.
Since Windows Server 2012 and Windows 8.1 TLS 1.2 is enabled by default. So, you should be fine.

However, it is worth to check if TLS 1.2 is enabled at OS level and in the registry (this also affects IIS (7.x), SQL Server (2012), Reporting Services, etc. depending on the build version). The default security protocol depends on the following registry entry.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319: SchUseStrongCrypto to DWORD 1

Check if the registry key "SchUseStrongCrypto" is set to 1. This will force .NET apps to avoid using SSL3.0 or TLS1.0 and always use the strongest protocol available.

I hope this helps!

like image 98
wp78de Avatar answered Oct 26 '22 23:10

wp78de