Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Trouble with HttpWebRequest Authorization

0.00/5 (No votes)
25 Apr 2014 1  
RFC 2617 on the net-platform

Introduction

The HttpWebRequest class is very useful to work with internet data, but it got some problems. When calling different secure endpoints, only the first is working and for the rest the auth is failing. To be honest, it is a bug in the complete net-platform, and I hope it gets fixed sooner than later.

Background

In digest authorization on Windows Phone 8 is a problem which led me to some trouble and headaches before I figured out the solution.

After some days, I found the solution on stackoverflow which got also mentioned on the MSDN blog.

To understand digest authorization, read this.

Using the Code

The provided code consists of three functions. Hint: It isn't a project, but only the 3 functions.

First creating a request, then writing the soap-message, which got refused and then starting the auth with a own digest. In the end is the link to the stackoverflow postings in which a detailed solution is provided.

    private void CreateCall()        
    {
        Uri uri = new Uri(m_SoapEndPoint,UriKind.Absolute);
        HttpWebRequest request = WebRequest.Create( uri ) as HttpWebRequest;
        request.Method = "POST";
        request.UserAgent = "UPnP/1.0 Client 1.0";
        request.Headers["SOAPACTION"] = NameSpace + "#" + SoapMethod;
        request.ContentType = "text/xml;charset=\"utf-8\"";
        request.AllowAutoRedirect = false;
        request.UseDefaultCredentials = false;// of the currently logged on user.

        //works only for the first endpoint
        //request.Credentials = new NetworkCredential( Settings.User, Settings.Password );
    
        if( Nonce.Length > 0 )//if the call is restarted there is a nonce
        {
            String sAuthentification = GetAuthorizationMd5();
            request.Headers[HttpRequestHeader.Authorization] = sAuthentification;
        }

        // Make async call for request stream. Callback will be called on a background thread.  
        IAsyncResult asyncResult = request.BeginGetRequestStream(OnRequestStream, request);
    }

     private void OnRequestStream( IAsyncResult ar )
        {
            try
            {
                if( ar.IsCompleted )
                {
                    HttpWebRequest request = (HttpWebRequest) ar.AsyncState;
                    using( Stream requestStream = request.EndGetRequestStream( ar ) )
                    {
                        using( StreamWriter streamWriter = new StreamWriter( requestStream ) )
                        {

                            // Write to the request stream.
                            streamWriter.Write( m_SoapBody );

                                streamWriter.Flush();
                                streamWriter.Close();
                            }
                        }
                        // Make async call for response. Callback will be called on a background thread.
                        IAsyncResult result = request.BeginGetResponse( OnResponseStream, request );
                    }
                }
            }
            catch (WebException we)
            {
                m_bRunning = false;
                Status = "OnRequestStream mit WebException: " + we.Message;
                MessageBox.Show( Status );
            }
        }

    private void OnResponseStream( IAsyncResult ar )
        {
            try
            {
                if( ar.IsCompleted )
                {
                    HttpWebRequest request = ar.AsyncState as HttpWebRequest;

                    using( WebResponse response = request.EndGetResponse( ar ) as HttpWebResponse )
                    {
                        // get the stream containing the response from the async call
                        using( Stream streamResult = response.GetResponseStream() )
                        {
                            using( StreamReader reader = new StreamReader( streamResult ) )
                            {
                                m_Response = reader.ReadToEnd();
                                reader.Close();

                                NotifySoapResponse();
                            }
                        }
                    }
                }
            }
            catch( NotSupportedException nse )
            {
                Status = nse.Message;
            }
            catch( SecurityException se )
            {
                Status = se.Message;
            }
            catch( WebException we )
            {
                Debug.WriteLine( "OnResponseStream-WebException: " + we.Message);

                if( Nonce.Length == 0 )
                {
                    HttpWebResponse response = (HttpWebResponse) we.Response;

                    if( response.StatusCode == HttpStatusCode.Unauthorized )
                    {
                        WebHeaderCollection coll = response.Headers;

                        String authHeader = we.Response.Headers["WWW-Authenticate"];
                        Debug.WriteLine( "Auth Header " + authHeader );
                        
                        ComputeAuthAndRestartTheCall();
                        
                        return;
                    }
                }
                else
                {
                    Nonce = "";
                }
            }
            catch( InvalidOperationException ie )
            {
                Status = ie.Message;
            }
        } 

In ComputeAuthAndRestartTheCall();, you need to do your md5-auth and restart the call.

Points of Interest

This caused me a lot of trouble and I hope that somebody can learn from it. Here are the links to some interesting websites:

History

  • Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here