/egilh

Learning by doing

Real PreAuthenticate for .NET Web Services

Posted on Wednesday, August 29, 2007 10:38 AM

.NET Web Service clients do not send authentication details with the requests so you get a traffic pattern like this

Request 1:

Client: GET someUrl
Server: 401 WWW-Authenticate Basic
Client: GET with Authorization header
Server: 200 OK

Request 2:

Client: GET someUrl
Server: 401 WWW-Authenticate Basic
Client: GET with Authorization header
Server: 200 OK

The PreAuthenticate property improves the situation if you make many repeated calls to a web service.

Request 1:

Client: GET someUrl
Server: 401 WWW-Authenticate Basic
Client: GET with Authorization header
Server: 200 OK

Request 2:

Client: GET someUrl with Authorization header
Server: 200 OK

The first request does not contain the Authorization header but the subsequent requests do. I do not like this feature as the systems I work on usually make one single web service request per client request so I always get 401 errors.

You can fix the problem by manually inserting the Authorization header in the requests. Do not modify the Web Service client generated by Visual Studio as you will loose your changes if you update the Web Reference.  Extend the Web Service client instead and override the GetWebRequest method:

public class WSTestPreAuthenticate : WSTest

{

    protected override System.Net.WebRequest GetWebRequest(Uri uri)

    {

        HttpWebRequest request;

        request = (HttpWebRequest)base.GetWebRequest(uri);

 

        if (PreAuthenticate)

        {

            NetworkCredential networkCredentials =

                Credentials.GetCredential(uri, "Basic");

 

 

            if (networkCredentials != null)

            {

                byte[] credentialBuffer = new UTF8Encoding().GetBytes(

                    networkCredentials.UserName + ":" +

                    networkCredentials.Password);

                request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);

            }

        }

        return request;

    }

}

The change above means that PreAuthentication works as it should since it always sends the Authorization header

Request 1:

Client: GET someUrl with Authorization header
Server: 200 OK

The client has to set the PreAuthenticate header and any custom credentials:

WSTestPreAuthenticate test = new WSTestPreAuthenticate ();

test.PreAuthenticate = true;

test.Url = "http://localhost/WSTest/WSTest.asmx";

test.Credentials =

new System.Net.NetworkCredential("user", "password");

int ret = test.Method("test");




Feel free to drop a few cents in the tip jar if this post saved you time and money

Post Comment
Title
 

Name
 

Url

Protected by Clearscreen.SharpHIPEnter the code you see:
Comment