Using HttpWebRequest with Credential Manager

A little know fact is that the .NET framework will use the stored credentials in the Credential Manager when accessing a network resource if the credentials exist for that particular resource (host).  I intend to clear up how this functionality works for the HttpWebRequests (you could extend this to WebService calls as well).

In Internet Explorer, you can access a website that challenges you for credentials by filling in a username and password when the dialog is presented and asks you for authentication.  If you check ‘Remember my password’ these credentials will be stored in protected storage (Credential Manager).  You can see the stored credentials by running this command: Control Keymgr.dll.  These credentials are stored in protected storage in each user’s My folder.  You can store these credentials by using control Keymgr.dll, by using the interface available in Internet Explorer or by using C++/C and the Credentials API’s (Such as CredWrite).  If you do not check ‘Remember my password’ then these credentials are not stored in Credential Manager and .NET will not be able to use these credentials.

The .NET framework can use the currently logged on user’s credentials to authenticate but if you have a web site that requires different credentials you can use store these credentials in Credential Manager and .NET will use these credentials instead of the currently logged on user credentials.  To illustrate this I put together a real simple sample.

The target web server in my sample is jpsandershv2003.  I only enabled Windows Integrated Authentication in IIS on that box.  I then created a User ID JPSGuest on that IIS machine.  Finally I wrote a real simple .NET console application to create an HttpWebRequest and get the response.

   HttpWebRequest aReq;

   HttpWebResponse aResp;

        

   aReq = WebRequest.Create("https://jpsandershv2003/") as HttpWebRequest;

   aReq.UseDefaultCredentials = true;

  aResp = aReq.GetResponse() as HttpWebResponse;

  aResp.Close();

When you run this code it will first look in the credential manager first for the credentials for attaching to jpsandershv2003 and if found use those, otherwise the Currently Logged on User credentials will be used.  In my example since I was logged on as jpsanders to my machine I expect that the credentials used should be my domain credentials jpsanders.  I turned on logging and ensured the IIS log was logging the username and sure enough, jpsanders was authenticated in IIS.

My next goal was to see if I could change this default behavior and make it log on using the jpsandershv2003\JPSGuest user credentials.  Using the command control keymgr.dll I was able to add the credential as a Windows logon credential:

 

 

Now when I ran the console application I saw success in the IIS log!  I was logging in now as JPSGuest.

Taking a fiddler (https://fiddlertool.com) trace of Internet Explorer also confirmed I was using the stored credentials and these were NTLM credentials. 

Domain: jpsandershv2003
User: JPSGuest
Host: JPSANDERS3

Can I store credentials and have it use Kerberos?  In theory yes, simply type domain based credentials in.  However I could not test this because I only have one logon to my domain and you cannot save your currently logged on credentials in the Credential Manager. 

What about basic and digest?  NO, this would be a huge security hole.  Can you tell me why (it should be obvious)?

Note that the credentials used are independent of the PORT used.  So if I change the server to bind HTTP traffic on port 8089 then change my code to access https://jpsandershv2003:8089 the code will still access the web site using the stored credentials.

To revert back to the interactive user, simply delete the credentials stored for jpsandershv2003.

Further observations

What is the second radio button for (A Web site or program credentials)?  This is for programs that are writing against the credentials API directly.  Some examples of this are Terminal Server (RDP) and Windows Live credentials.  Here are some great links about the APIs:
https://msdn.microsoft.com/en-us/library/aa374789(VS.85).aspx
https://msdn.microsoft.com/en-us/library/aa480470.aspx

NOTE: Because the credentials are stored in the context of the logged on user, this technique will not work for non interactive user accounts such as the service accounts and ASP.NET applications.

 

Please send me a quick note if you found this Blog helpful!