How can I retrieve Basic Authentication credentials from the header?

user4041873 picture user4041873 · Sep 15, 2014 · Viewed 83.3k times · Source

I am trying to write some simple tests User Authentication mechanism which uses Basic Authentication. How can I retrieve the credentials from the header?

string authorizationHeader = this.HttpContext.Request.Headers["Authorization"];

Where do I go from here? There are several tutorials but I new to .NET and authentication, could you explain in your answer exactly step-by-step the what and why you are doing.

Answer

Dawid O picture Dawid O · Sep 15, 2014

From my blog:

This will explain in detail how this all works:

Step 1 - Understanding Basic Authentication

Whenever you use Basic Authentication a header is added to HTTP Request and it will look similar to this:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Source: http://en.wikipedia.org/wiki/Basic_access_authentication

"QWxhZGRpbjpvcGVuIHNlc2FtZQ==" is just "username:password" encoded in Base64(http://en.wikipedia.org/wiki/Base64). In order to access headers and other HTTP properties in .NET (C#) you need to have access to the current Http Context:

HttpContext httpContext = HttpContext.Current;

This you can find in System.Web namespace.

Step 2 - Getting the Header

Authorization header isn't the only only one in the HttpContext. In order to access the header, we need to get it from the request.

string authHeader = this.httpContext.Request.Headers["Authorization"];

If you debug your code you will see that the content of that header looks similar to this:

Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Step 3 - Checking the header

You've already extracted the header now there are several things you need to do:

  1. Check that the header isn't null
  2. Check that the Authorization/Authentication mechanism is indeed "Basic"

Like so:

if (authHeader != null && authHeader.StartsWith("Basic")) {
    //Extract credentials
} else {
    //Handle what happens if that isn't the case
    throw new Exception("The authorization header is either empty or isn't Basic.");
}

Now you have check that you are have something to extract data from.

Step 4 - Extracting credentials

Removing "Basic " Substring

You can now attempt to get the values for username and password. Firstly you need to get rid of the "Basic " substring. You can do it like so:

string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();

See the following links for further details:

  1. http://msdn.microsoft.com/en-us/library/system.string.substring(v=vs.110).aspx
  2. http://msdn.microsoft.com/en-us/library/t97s7bs3(v=vs.110).aspx

Decoding Base64

Now we need to decode back from Base64 to string:

//the coding should be iso or you could use ASCII and UTF-8 decoder
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));

Now username and password will be in this format:

username:password

Splitting Username:Password

In order to get username and password we can simply get the index of the ":"

int seperatorIndex = usernamePassword.IndexOf(':');

username = usernamePassword.Substring(0, seperatorIndex);
password = usernamePassword.Substring(seperatorIndex + 1);

Now you can use these data for testing. Good luck!

PS: the final code may look like this:

HttpContext httpContext = HttpContext.Current;

string authHeader = this.httpContext.Request.Headers["Authorization"];

if (authHeader != null && authHeader.StartsWith("Basic")) {
    string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
    Encoding encoding = Encoding.GetEncoding("iso-8859-1");
    string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));

    int seperatorIndex = usernamePassword.IndexOf(':');

    var username = usernamePassword.Substring(0, seperatorIndex);
    var password = usernamePassword.Substring(seperatorIndex + 1);
} else {
    //Handle what happens if that isn't the case
    throw new Exception("The authorization header is either empty or isn't Basic.");
}