none
NTLM Authentication not working (400 and 500) RRS feed

  • Question

  • Hi I have a simple Client:

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    
    namespace Ntlm
    {
        public class Program
        {
            #region Methods
    
            private static void Main()
            {
                var t = new Program();
                Console.WriteLine("Starting....");
                t.Run();
            }
    
            private void Run()
            {
                // First procedure:
                // create a WSHttpBinding that uses Windows credentials and message security
                var myBinding = new WSHttpBinding
                {
                    Security =
                    {
                        Mode = SecurityMode.Message, Message = {ClientCredentialType = MessageCredentialType.Windows}
                    }
                };
    
                // 2nd Procedure:
                // Use the binding in a service
                // Create the Type instances for later use and the URI for 
                // the base address.
                var contractType = typeof(ICalculator);
                var serviceType = typeof(Calculator);
                var baseAddress = new Uri("http://localhost:8036/SecuritySamples");
    
                // Create the ServiceHost and add an endpoint, then start
                // the service.
                var myServiceHost = new ServiceHost(serviceType, baseAddress);
                myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator");
    
                //enable metadata
                var smb = new ServiceMetadataBehavior {HttpGetEnabled = true};
                myServiceHost.Description.Behaviors.Add(smb);
    
                myServiceHost.Open();
                Console.WriteLine("Listening");
                Console.WriteLine("Press Enter to close the service");
                Console.ReadLine();
                myServiceHost.Close();
            }
    
            #endregion
        }
    
        [ServiceContract]
        public interface ICalculator
        {
            #region Public Methods and Operators
    
            [OperationContract]
            double Add(double a, double b);
    
            #endregion
        }
    
        public class Calculator : ICalculator
        {
            #region Public Methods and Operators
    
            public double Add(double a, double b)
            {
                return a + b;
            }
    
            #endregion
        }
    }

    and in the app.config there is nothing other than the system.diagnostics

    now, I am trying to send a 

    HttpWebRequest

    to get a response from this service. The Wcf Test Client can to this of course, it authenticates itself with this service while scanning the service and then sends a request like this:

    <s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
      <s:Header>
        <a:Action s:mustUnderstand="1">http://tempuri.org/ICalculator/Add</a:Action>
        <a:MessageID>urn:uuid:dcac8c1e-b552-4011-8cf6-a0d3829aec71</a:MessageID>
        <a:ReplyTo>
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
      </s:Header>
      <s:Body>

    NOW: depending on what I send i get different results with the NTLM authentication

    CASE 1:

    i send the request

    <?xml version="1.0" encoding="utf-8"?>
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
      <s:Body>
        <Add xmlns="http://tempuri.org/">
          <a>1</a>
          <b>1</b>
        </Add>
      </s:Body>
    </s:Envelope>


    with the headers 

    Content-Type application/soap+xml;charset=utf-8;action="http://tempuri.org/ICalculator/Add"

    I get a 400 Bad Request, and this is how I send it:

                var req = WebRequest.CreateHttp(m.GetUri());
                req.Timeout = Timeout;
                req.AllowAutoRedirect = m.AutoRedirect;
                req.Method = "Post";
                req.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
                req.Credentials = new CredentialCache {
                        { Destination.Host, Destination.Port, "NTLM", new NetworkCredential(Config.Username, Config.Password, Config.AuthenticationDomain) },
                };
                req.Proxy.Credentials = request.Credentials;
    
                req.ContentType = "application/soap+xml;charset=utf-8;action=\"http://tempuri.org/ICalculator/Add\""
    
    
    


    CASE 2: I send the payload 

    <?xml version="1.0" encoding="utf-8"?>
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
      <Header xmlns="http://www.w3.org/2003/05/soap-envelope">
        <Action xmlns="http://www.w3.org/2005/08/addressing">http://tempuri.org/ICalculator/Add</Action>
      </Header>
      <s:Body>
        <Add xmlns="http://tempuri.org/">
          <a>1</a>
          <b>1</b>
        </Add>
      </s:Body>
    </s:Envelope>

    with the same settings as above, and I get 500 Internal Server Error 

    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
      <s:Header>
        <a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>
      </s:Header>
      <s:Body>
        <s:Fault>
          <s:Code>
            <s:Value>s:Sender</s:Value>
            <s:Subcode>
              <s:Value xmlns:a="http://schemas.xmlsoap.org/ws/2005/02/sc">a:BadContextToken</s:Value>
            </s:Subcode>
          </s:Code>
          <s:Reason>
            <s:Text xml:lang="de-AT">The message could not be processed. This is most likely because the action 'http://tempuri.org/ICalculator/Add' 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.</s:Text>
          </s:Reason>
        </s:Fault>
      </s:Body>
    </s:Envelope>

    After analyzing the WCF logs, fiddler, and wireshark, I can see that the message is send bare in my case, and the challenge is not arriving somehow, and no 401 for my code. what is the problem? I have the same problem with Kerberos as well



    • Edited by omidchini Thursday, November 29, 2018 9:23 AM Pretty Print the payload
    Monday, November 26, 2018 1:00 PM

All replies

  • Your WCF operational contract would need to be using a Post attribute in order to receive a Post request from the client. If the request is not understood, then you get a HTTP 400 bad request error code

    HTTP 500 means that the service through an unhandled exception, IIS swallowed the exception and IIS through the HTTP 500 error code. 


    • Edited by DA924x Tuesday, November 27, 2018 5:08 AM
    Tuesday, November 27, 2018 5:07 AM
  • Hi Omidchini,
    According to your description, you want to communicate with client directly via HttpWebrequest. 
    As far as I know, when we use wshttpbinding and windows ClientCredentialType to create channel on the internet, there are at least three steps to authenticate the client. during the authentication the client should negotiate the authenticate way with the server-side and get the security token finally. 

    This security token is then used to communicate with the server side.

    You could check the authentication process in Fiddler.

    https://i.stack.imgur.com/O3Qgq.png

    In my opinion, if you want to receive the server-side challenge, you should strictly follow the authentication steps unless you use SecurityMode=None, which only needs to provide parameters and request methods in one Http communication to get a response.

    Besides, you could also use the webhttpbinding to create restful-style web service and invoke it with httpwebrequest.

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/wcf-web-http-programming-model

    Best Regards
    Abraham
    Tuesday, November 27, 2018 10:00 AM
    Moderator
  • The 400 Error I really cannot comprehend, and as for the IIS I need to specify that both applications are running locally with no IIS involved.

    All the sources I found mention that the HttpWebRequest handels the authentication internally with the AuthenticationManager. I still have no clue how to fix this on my end. What I really dont understand is how the WCF Test Client is working, and not ours. I have attached the svclogs of the successful call of the WCF Test Client and of our client (https://tricentisgmbh-my.sharepoint.com/:f:/g/personal/o_foroushan_tricentis_com/ErCuyYm4izVKm9VyLEgW6xMBVOVC72Z_Y3PkUOz8OCDnew?e=pxk6l0). The request of the WCF Test client looks like this

    <s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
      <s:Header>
        <a:Action s:mustUnderstand="1">http://tempuri.org/ICalculator/Add</a:Action>
        <a:MessageID>urn:uuid:ed6863ed-e811-4589-b70d-e729cb8c1f84</a:MessageID>
        <a:ReplyTo>
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
      </s:Header>
      <s:Body>
        <Add xmlns="http://tempuri.org/">
          <a>1</a>
          <b>1</b>
        </Add>
      </s:Body>
    </s:Envelope>

    and the response

    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <s:Header>
        <a:Action s:mustUnderstand="1" u:Id="_2">http://tempuri.org/ICalculator/AddResponse</a:Action>
        <ActivityId CorrelationId="b9bc0469-cf3f-4659-a705-1907d44870ac" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000</ActivityId>
        <a:RelatesTo u:Id="_3">urn:uuid:b2b7b85e-ba24-4f67-97ba-c375d156cea9</a:RelatesTo>
        <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <u:Timestamp u:Id="uuid-ff14155c-f688-46d0-a061-3bb98f51a911-7">
            <u:Created>2018-11-28T10:34:28.803Z</u:Created>
            <u:Expires>2018-11-28T10:39:28.803Z</u:Expires>
          </u:Timestamp>
          <c:DerivedKeyToken u:Id="uuid-ff14155c-f688-46d0-a061-3bb98f51a911-5" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
            <o:SecurityTokenReference>
              <o:Reference URI="urn:uuid:d1769bdf-86bb-4bdb-9e2d-8fa7f38776ea" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
            </o:SecurityTokenReference>
            <c:Offset>0</c:Offset>
            <c:Length>24</c:Length>
            <c:Nonce>iVmHjhZrEd3GhaVIXgiO3Q==</c:Nonce>
          </c:DerivedKeyToken>
          <c:DerivedKeyToken u:Id="uuid-ff14155c-f688-46d0-a061-3bb98f51a911-6" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
            <o:SecurityTokenReference>
              <o:Reference URI="urn:uuid:d1769bdf-86bb-4bdb-9e2d-8fa7f38776ea" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
            </o:SecurityTokenReference>
            <c:Nonce>leIT5FfhEcCZZloMPRXGSQ==</c:Nonce>
          </c:DerivedKeyToken>
          <e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
            <e:DataReference URI="#_1" />
            <e:DataReference URI="#_4" />
          </e:ReferenceList>
          <e:EncryptedData Id="_4" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
            <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
              <o:SecurityTokenReference>
                <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" URI="#uuid-ff14155c-f688-46d0-a061-3bb98f51a911-6" />
              </o:SecurityTokenReference>
            </KeyInfo>
            <e:CipherData>
              <e:CipherValue>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</e:CipherValue>
            </e:CipherData>
          </e:EncryptedData>
        </o:Security>
      </s:Header>
      <s:Body u:Id="_0">
        <AddResponse xmlns="http://tempuri.org/">
          <AddResult>2</AddResult>
        </AddResponse>
      </s:Body>
    </s:Envelope>

    Wednesday, November 28, 2018 11:22 AM
  • As I mentioned in the post below, we are not using IIS and both the WCf and the Client are on my local machine. And I really need to know how the WCF Test Client can successfully send the request, but our client fails to do so.
    • Edited by omidchini Wednesday, November 28, 2018 11:32 AM
    Wednesday, November 28, 2018 11:31 AM
  • Hi Omidchini,
    According to your description, you want to communicate with client directly via HttpWebrequest. 
    As far as I know, when we use wshttpbinding and windows ClientCredentialType to create channel on the internet, there are at least three steps to authenticate the client. during the authentication the client should negotiate the authenticate way with the server-side and get the security token finally. 

    This security token is then used to communicate with the server side.

    You could check the authentication process in Fiddler.

    In my opinion, if you want to receive the server-side challenge, you should strictly follow the authentication steps unless you use SecurityMode=None, which only needs to provide parameters and request methods in one Http communication to get a response.

    Besides, you could also use the webhttpbinding to create restful-style web service and invoke it with httpwebrequest.


    Best Regards
    Abraham

    The thing is, the HttpWebRequest is supposedly capable of handling all of these steps internally (https://docs.microsoft.com/en-us/dotnet/framework/network-programming/ntlm-and-kerberos-authentication) 

    Wednesday, November 28, 2018 11:38 AM
  • As I mentioned in the post below, we are not using IIS and both the WCf and the Client are on my local machine. And I really need to know how the WCF Test Client can successfully send the request, but our client fails to do so.

    If you are using WCF test client, the you are using IIS, which maybe IIS Express. There is no way you are going the get an HTTP 500 and 400 error with a Post from the client, unless IIS of some form is involved.
    Wednesday, November 28, 2018 2:11 PM
  • Me and our architect are pretty sure we are not using IIS. Just to be sure, I checked and stopped IIS Express, and checked the IIS (sadly I cant post pictures to show that there are no sites in IIS and no bindings to the port 8036) but we can say that IIS is not involved in the WCF service. the WCF Test Client we are talking about is located in: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\WcfTestClient.exe

    I have the whole source code of the WCF Client (the calculator) in the first post if that helps

    Thursday, November 29, 2018 9:13 AM
  • now, I am trying to send a 

    HttpWebRequest

    If you are not trying to contact to a Web server, thenwhy are you using HTTPWebRequest? 

    WCFTestClint may have changed, becuase the last time I used it was when WCF first came out  like around year 2008, and the test clinet only worked for WCF ASP.NET.

    So what is hosting the WCF service and is the WCF service using  the TCP/IP protocol, HTTP protocol  or what is the protocol the WCF service is using?

    I see that console program that seems kind of questionable. 


    • Edited by DA924x Thursday, November 29, 2018 10:40 AM
    Thursday, November 29, 2018 10:39 AM
  • The problem is that our product NEEDS to be able to communicate with the WCF service console program as it is.

    The reason we are using the HttpWebRequest/WebRequest is actually because according to the documentations these classes manage Kerberos and NTLM internally with the challenges and everything

    https://docs.microsoft.com/en-us/dotnet/framework/network-programming/ntlm-and-kerberos-authentication

    https://docs.microsoft.com/en-us/dotnet/api/system.net.httpwebrequest.unsafeauthenticatedconnectionsharing?view=netframework-4.7.2#System_Net_HttpWebRequest_UnsafeAuthenticatedConnectionSharing

    https://stackoverflow.com/questions/3562979/making-a-web-request-to-a-web-page-which-requires-windows-authentication

    https://stackoverflow.com/questions/39787404/c-sharp-webclient-ntlm-authentication-starting-for-each-request

    https://github.com/dotnet/corefx/issues/25988

    just some examples which show from what I can see that the classes are supporting the NTLM authentication procedure. If not these, how would you suggest we send the request and get the response while authenticating NTLM and not writing the whole procedure ourselves? Any help would be appreciated.

    Thursday, November 29, 2018 12:24 PM
  • NTLM is just a form of Windows autentication.

    I don't know maybe you need to be using WCF over NET.TCP, if this solution is to be used within the corporate network on the LAN.

    https://www.codeproject.com/Articles/717327/WCF-NetTcp-Binding

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-with-windows-authentication

    Thursday, November 29, 2018 3:18 PM