none
Why does every kerberos authenticated call to a WCF data service require a 401 authentication step?

    Question

  • We've recently been doing some performance investigation around our WCF services and have found that every call to our OData service results in an HTTP 401 then an HTTP 200. The services are hosted in IIS 7.5 or later and using the 5.4.0 versions of the Microsoft.Data.* assemblies. The services use Windows Authentication and are configured to use Kerberos rather than NTLM.

    The service runs in a dedicated app pool which uses a domain account to support load balancing. The appropriate HTTP SPN has been added to the domain service account. The web application has the authPersistNonNTLM setting enabled to allow session level kerberos authentication rather than per call. The data service url is trusted by the client and so kerberos tokens can be used.

    A simple test WCF SOAP service was created alongside the WCF Data service to compare the traffic profiles of regular WCF with a WCF Data service. The SOAP service has a single 401 for the first request then all subsequent calls do not require reauthentication. Examining the HTTP messages show that a Connection: [Keep-Alive] header is present in the call and that the response issues a Persistent-Auth: true header. Even if the WCF SOAP proxy is closed and reconstructed we do not get additional 401 requests.

    The WCF Data Service client issues a 401 on every request. The HTTP messages show that the same Connection: [Keep-Alive] and Persistent-Auth headers are present.

    Note that observing the traffic using either Fiddler or the Web Proxy included with the Microsoft Message Analyzer does not show the additional 401 traffic. It can be seen however when using the local link layer viewer for the Microsoft Message Analyzer or Wireshark. This seems to be explained by Eric Lawrence in this post: 

    http://blogs.telerik.com/fiddler/posts/13-02-28/help!-running-fiddler-fixes-my-app-

    Fiddler is keeping open the connection which correlates with our observations that the WCF Data Service calls are faster when Fiddler is running and a constrained connection (WAN / high latency) exists between the client and the server.

    Is there anyway to configure the WCF Data Service / client to avoid the additional 401 request on every call? If not, why does the data service require this when a WCF SOAP service does not?

    Many thanks,

    Stef


    • Edited by stefsewell Monday, June 09, 2014 11:22 PM Spelling correction
    Monday, June 09, 2014 10:37 PM

Answers

  • Hello,

    It seems to be a default behavior with WebRequest (or WebClient) to re-authenticate on every request that requires authorization and it's part of the HTTP authentication protocol, used to discover the authentication scheme the server uses, and it cannot be changed.

    Update:

    After researching online for a while, I found there is a property named Request.PreAuthenticate and in WCF Data Service client side, there is an event named SendingRequest2  which is fired when a new HttpWebRequest has been created. You can have a try to set its value to true before send the value as:

    static void Main(string[] args)
    
            {
    
                Server20140610.DFDBEntities db = new Server20140610.DFDBEntities(new Uri("http://localhost:59343/Server20140610.svc"));
    
                db.SendingRequest2 += db_SendingRequest2; 
    
                var result = db.Orders.ToList();
    
            }
    
            static void db_SendingRequest2(object sender, SendingRequest2EventArgs e)
    
            {
    
                ((HttpWebRequestMessage)e.RequestMessage).HttpWebRequest.PreAuthenticate = true;
    
            }
    

    For details, you can check this article:

    http://weblog.west-wind.com/posts/2010/Feb/18/NET-WebRequestPreAuthenticate-not-quite-what-it-sounds-like

    For some limitions, I cannot test this code, if this does not work for you, please let me know.

    Regards.

    Tuesday, June 10, 2014 6:17 AM
    Moderator

All replies

  • Hello,

    It seems to be a default behavior with WebRequest (or WebClient) to re-authenticate on every request that requires authorization and it's part of the HTTP authentication protocol, used to discover the authentication scheme the server uses, and it cannot be changed.

    Update:

    After researching online for a while, I found there is a property named Request.PreAuthenticate and in WCF Data Service client side, there is an event named SendingRequest2  which is fired when a new HttpWebRequest has been created. You can have a try to set its value to true before send the value as:

    static void Main(string[] args)
    
            {
    
                Server20140610.DFDBEntities db = new Server20140610.DFDBEntities(new Uri("http://localhost:59343/Server20140610.svc"));
    
                db.SendingRequest2 += db_SendingRequest2; 
    
                var result = db.Orders.ToList();
    
            }
    
            static void db_SendingRequest2(object sender, SendingRequest2EventArgs e)
    
            {
    
                ((HttpWebRequestMessage)e.RequestMessage).HttpWebRequest.PreAuthenticate = true;
    
            }
    

    For details, you can check this article:

    http://weblog.west-wind.com/posts/2010/Feb/18/NET-WebRequestPreAuthenticate-not-quite-what-it-sounds-like

    For some limitions, I cannot test this code, if this does not work for you, please let me know.

    Regards.

    Tuesday, June 10, 2014 6:17 AM
    Moderator
  • Hi Fred,

    Awesome thanks - just tested setting this flag and there is the initial 401 but it is not repeated on subsequent requests.

    Cheers,

    Stef

    Wednesday, June 11, 2014 11:12 PM