Locked Why does pre-authenticate fail to authenticate?

  • Thursday, May 10, 2012 6:32 PM
     
     

    I have a simple problem (so it would seem) with the preauthenicate feature.  In this simple program, I can not get the .NET library to preauthenticate my request.  I've tried variations but to no avail.  Maybe I just don't understand how thsi feature works or my webserver does something unexpected.  Can anyone suggest a change that might work?

                String transport = args[0];
                String username = args[1];
                String password = args[2];
                String schema;
                String hostName;

                hostName = transport + "://dev.acadiasoft.com";

                schema = "/schema1";

                Uri URLAddress = new Uri(hostName + schema + "/status");
                Uri hostUri = new Uri(hostName);

                Console.WriteLine("Making a GET call to " + URLAddress + ".");

                // Microsoft .Net way of doing authentication
                NetworkCredential myCred = new NetworkCredential(username, password);
                CredentialCache myCache = new CredentialCache();
                myCache.Add(hostUri, "Basic", myCred);
                try
                {
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URLAddress);

                    request.Method = "GET";

                    request.Credentials = myCache;
                    request.PreAuthenticate = true;

                    // This actually where the preauthentication takes place - manually adding the auhentication header
                    // request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password)));

                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    Console.Write("\nGetting a response ...");
                    Console.WriteLine("Web response is {0}.", request.HaveResponse);
                    Console.WriteLine("Content type is {0}", response.ContentType);

                    Stream receiveStream = response.GetResponseStream();

                    StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

                    Console.WriteLine("\nContent length is {0}", response.ContentLength);
                    Console.WriteLine(readStream.ReadToEnd());
                    response.Close();
                    readStream.Close();

                    Console.WriteLine("Press <Enter> to continue");
                    Console.ReadLine();

                }

    This should work but I always have to manually add the authorization header.  I've done Fiddler2 traces and I see the authenticate header come back from the server.  But I never see an authorization header from the request unless I specifically code for it.

    -Dan

All Replies

  • Thursday, May 10, 2012 7:45 PM
     
     

    You should be using 3 different method.  I see you doing all the correct setting of the parmaters and the credentials, but you arent' actually communicating with the server.

    1) Open  - Makes a connection to the server and validates the credientals

    2) Send - Transmits the "GET" message which will start the data transfer

    3) Responsetext - Read the data from the client receive bufffer


    jdweng

  • Friday, May 11, 2012 9:36 PM
     
     

    From MSDN (http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.preauthenticate.aspx)

         true to send an HTTP Authorization header with requests after authentication has taken place; otherwise, false. The default is false.

    Underline is my emphasis.

    That is it does not control whether an authentication header is included in a first request, instead it controls whether an authentication header is included in a second and subsequent request if a previous request did use the authentication header.

    Is your server not responding with a 401?


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.


  • Friday, May 11, 2012 9:37 PM
     
     
    @JoelEngineer Huh? Are you saying that there are .NET methods called Open, Send and Responsetext that a program needs to call??

    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

  • Friday, May 11, 2012 9:58 PM
     
     
    I forgot about the differences between th eolder libraries and the newer libraries.  I had VBA code which uses an old version of the library, and I forgot it is significantly different from the Net library.

    jdweng

  • Monday, May 14, 2012 2:24 PM
     
     

    As I suspected - - I did not understand the intentions behind this feature (I still don't).  Please allow me to clarify. 

    I'm trying to build a RESTful client to a known RESTful web services API (server).  This is strictly a machine-to-machine implementation.  Since the RESTful web services in question require authenticaion with each call, this would not be an appropriate API to include.  I fail to see the usefulness of this feature; if it requires me to deal with an authenticate server response on the first call, but not on subsequent responses.  It is much easier (1 line of code) to simply add the appropriate header to every request. 

                    // This actually where the preauthentication takes place - manually adding the auhentication header
                    request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password)));

    Clearly, the pre-authentication property was designed to address some other programming problem.  I am curious though, has anyone else found a good use for this feature?  Something must have prompted the engineers to add this.

    Thanks for help!  You've answered my question.

    Dan

  • Monday, May 14, 2012 2:42 PM
     
     

    All Network protocols in the Net library are derived from RFC specifications developed by the IEEE in the 1970s.  The methods are just trying to meet the RFC requirements.  The Class and methods that Microsoft developed are trying to impliments all the RFC features.  I haven't used all the Net library functions to know if they all work exactly as the RFC specify.  I know of some issues with the Net Library wth respect to the RFC.  I haven't used the pre-authorization features so I can't comment specifically on your question about finding a good use for this feature.


    jdweng

  • Monday, May 14, 2012 3:44 PM
     
      Has Code
    Understood, but I don't understand the "first time" approach.  RFC 2617(1999), which addresses authentication, says in section 2 in the final paragraph what is quoted below.  There is no mention of a different first time.  It almost feels like Microsoft was taking an approach that works like a browser, instead of considering an actual REST implementation.  But I'm making assumptions, I don't really know. 

    A client MAY preemptively send the corresponding Authorization header with requests for resources in that space without receipt of another challenge from the server.

  • Monday, May 14, 2012 3:52 PM
     
     

    The RFC was puposely written that way because to allow different impimentations. You have to read carefully what happens at both the server and client.

    The client May send the pre Authorization.   Which means that any Server implimention will not reject the message because the header is included.  Now servers can be implimented two different ways. Some Servers will accept this authorization and not request an additional authorization.  Other serrvers will ask for additional challenges.


    jdweng

  • Tuesday, May 15, 2012 4:03 PM
     
     Answered

    I don't really see the problem.  When I use HttpWebRequest to access a web service I set the Credentials property (and PreAuthenticate=true) on every instance of HttpWebRequest instance.  For the very first instance it sends the request without the Authorization header and the server returns a 401 auth-required error with the "Authorization Basic" header.  The HttpWebRequest then automatically re-sends the request including the necessary Authorization header and all is well.

    For every subsequent request to the same server the HttpWebRequest instances automatically includes the Authorization header on the first request and again all is well.  If PreAuthenticate property was false the difference would be that for each new operation the request would first be send without the Authorization header and it would (automatically) have to re-send the request when it received the 401.

    So is your server not sending a 401 response with a valid Authorization Basic header??

    That's the only case where manually adding a Authorization Basic request header is required. One of the services I use officially uses OAuth and so sends 401 with an "Authorization OAuth" header.  However I know that it also accepts Basic auth so I add the header like you do.


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.


  • Tuesday, May 15, 2012 4:10 PM
     
     
    Alan: I agree there isn't a problem.  The issue was with the interpretation of RFC 2617(1999).  The RFC allows allows server to either authorize once at the connection or allows authorization during ever request.  You sometime shave to put on your lawyers hat to read these specifications.  The RFC committee didn't want to force software companies to add enhancements so they wrote the specifications to allow companies to slowly impliment changes.  The changes need to be both backwards compatable and forward compatible at both the server and clients ends.

    jdweng

  • Tuesday, May 15, 2012 5:56 PM
     
     

    I'm not sure what you mean by "... is your server not sending a 401 response with a valid Authorization Basic header??".  My client is not responding to the server sent "401 unauthorized" response.  Essentially, the code (in the first message) sends the request to the server, the server responds with the 401, and nothing is sent from the client to the server, ever again.  Here is a screen shot from Fiddler2 showing the results -