27

I would like to know why my asp.net application will not add the header to my post when it is named 'Authorization' but will work fine when I change one character, say "Authorizations". In documentation for other sites they always use the name "Authorization" so I would like to as well and at this point I just want to under stand why.

I have read a few topics about this but have not found any logical reason why.

Here is my code below:

string fileName = "c:\\xyz.xml";
string uri = "http://myserver/Default.aspx";
req = WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "text/xml";
byte[] authBytes = Encoding.UTF8.GetBytes("DDSServices:jCole2011".ToCharArray());
req.Headers.Add("Authorization", "BASIC " + Convert.ToBase64String(authBytes) );
req.Headers.Add("test", "test");
UTF8Encoding encoder = new UTF8Encoding();
byte[] data = encoder.GetBytes(this.GetTextFromXMLFile(fileName));
req.ContentLength = data.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
req.Headers.Add("Authorization", "BASIC" + Convert.ToBase64String(authBytes));
System.Net.WebResponse response = req.GetResponse();
System.IO.StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadToEnd();

The other annoying this is when i add the watched variable through fiddler it works fine.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Cody
  • 401
  • 1
  • 5
  • 8

3 Answers3

43

I was ran into a question how to add Authentication/Credentials to the headers. I found the solution in the following way.

string _auth = string.Format("{0}:{1}", "myUser","myPwd");
string _enc = Convert.ToBase64String(Encoding.ASCII.GetBytes(_auth));
string _cred = string.Format("{0} {1}", "Basic", _enc);
req.Headers[HttpRequestHeader.Authorization] = _cred;

Which gave me those headers I want (pasted Wireshark descriptions),

Authorization: Basic bXlVc2VyOm15UHdk\r\n
Credentials: myUser:myPwd

ahsteele
  • 26,243
  • 28
  • 134
  • 248
Independent
  • 2,924
  • 7
  • 29
  • 45
  • So how do you know for sure the encoding to use is ASCII? – Jeroen Wiert Pluimers Sep 20 '14 at 07:16
  • 1
    Nice point. The choosen encoding looks like a possible "hard to find"-source for bugs. I add the link http://stackoverflow.com/questions/7242316/what-encoding-should-i-use-for-http-basic-authentication for readers to find more information of how to decide. – Independent Sep 26 '14 at 13:07
11

For HTTP Basic Authorization, you should be using the Credentials property.

req.Credentials = new NetworkCredential("DDSServices", "jCole2011");

This should do what you want. Rather than setting the Authorization header.

  • or is there a logical reason? A very large third party company that we work with has documentation with their authorization in the same manner, so I would like to know the reason. – Cody Jan 13 '11 at 16:46
  • 1
    It is much better to use the NetworkCredential approach as Will suggests. However, your approach should also work fine, although I dont understand why you are doing it twice (one before call to GetRquestStream, and once after. You should do it jsut once before y ou call GetRequestStream. If it still doesnt work, get a trace log. Instructions at http://ferozedaud.blogspot.com/2009/08/tracing-with-systemnet.html – feroze Jan 13 '11 at 19:09
  • Can you tell me why it is better? Or where i can read about why it is better? To me it seems NetworkCredentials would be tied in with ad or forms authentication, I would rather the connection be through anonymous, then just verify. Either way though can someone just tell me why? I almost don't care about what at this point. – Cody Jan 13 '11 at 20:34
  • Well A) Because it works, and B) Because .NET will do the authentication negotiation for you automatically. Is the third party also using .NET? –  Jan 13 '11 at 23:53
  • More information on using NetworkCredential is here: http://msdn.microsoft.com/en-us/library/system.net.networkcredential.aspx - it can be used for any of the authentication schemes supported, and only uses the credentials you pass in. –  Jan 14 '11 at 00:00
  • 9
    NetworkCredential only sends the Authentication header after a 401 is received. This is probably not what you want... Use the old fashion way: `var credentialBuffer = new UTF8Encoding().GetBytes(aUserName + ":" + aPassword); request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);` – Hupperware Mar 07 '12 at 20:57
  • @Hupperware Unless you set PreAuthenticate=true. http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.preauthenticate.aspx –  Mar 12 '12 at 05:35
  • 2
    @WillHughes That's not true. I tried to use the PreAuthenticate=true but it was not working. The link you posted verifies that you need to catch the 401 the first time. "Property Value Type: System.Boolean true to send an HTTP Authorization header with requests after authentication has taken place; otherwise, false. The default is false." – Hupperware Mar 12 '12 at 20:39
3

NetworkCredential is a good solution but the site you are calling has to handle an unauthorized with a 401 AND a WWW-Authenticate header in the response.

Client:

request.Credentials = new CredentialCache {{aUri, "Basic", new NetworkCredential(aUserName, aPassword)}};

Server:

Response.ClearContent();
Response.StatusCode = 401;
Response.AddHeader("WWW-Authenticate", "Basic");
Response.End();

This will result in 2 hits to the server. The initial call will go to the server without credentials. When the server responds with a 401 AND the WWW-Authenticate header (with the type of authentication required), the request will be resent with the credentials in the request.

Hupperware
  • 979
  • 1
  • 6
  • 15
  • 3
    This is true, but sending back 401 Unauthorized, and the WWW-Authenticate header is part of the HTTP Spec. If you want to force sending the header on the first request, you can do so through the PreAuthenticate method. In Addition - IIS automatically handles sending back this response, as do other well-written HTTP servers such as Apache. It's how browsers know to display the password prompt dialog. –  Mar 12 '12 at 05:39