Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I retrieve Basic Authentication credentials from the header?

People also ask

Where are basic auth credentials stored?

If you're on Windows, you can put the cert in the user store for the app domain service account. Encrypt the basic auth credentials using the public key of the certificate. Store the encrypted credentials in your database, configuration file, or whatever your REST client uses.

How do I set basic authentication in HTTP header?

Basic Auth:The client sends HTTP requests with the Authorization header that contains the word Basic, followed by a space and a base64-encoded(non-encrypted) string username: password. For example, to authorize as username / Pa$$w0rd the client would send. Note: Base64 encoding does not mean encryption or hashing!


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"];

(Alternatively you may use AuthenticationHeaderValue.TryParse as suggested in pasx’s answer below)

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!

The Final Code

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.");
}

Just adding to the main answer, the best way to get rid of the "Basic" substring is to use AuthenticationHeaderValue Class:

var header = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
var credentials = header.Parameter;

It will throw a FormatException if the content of the header is not valid, e.g.: the "Basic" part is not present.

Alternatively if you do not want to have exception, use AuthenticationHeaderValue.TryParse


Awesome answer from @DawidO.

If you are just looking to extract the basic auth creds and rely on the .NET magic given you have HttpContext, this will also work:

  public static void StartListener() {
    using (var hl = new HttpListener()) {
      hl.Prefixes.Add("http://+:8008/");
      hl.AuthenticationSchemes = AuthenticationSchemes.Basic;
      hl.Start();
      Console.WriteLine("Listening...");
      while (true) {
        var hlc = hl.GetContext();

        var hlbi = (HttpListenerBasicIdentity)hlc.User.Identity;
        Console.WriteLine(hlbi.Name);
        Console.WriteLine(hlbi.Password);

        //TODO: validater user
        //TODO: take action
      }
    }
  }

Remember, using strings can be less secure. They will remain in memory untill they are picked by GC.