Basic authentication is one of the most fundamental ways in which authentication can be performed. It does not require multiple calls and is very easy to learn. In this article, I will present how to use C# (usually with WCF) to extract basic authentication credentials from the request.
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==
"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:
1 |
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.
1 |
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:
1 2 3 4 5 6 |
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:
1 |
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:
1 2 |
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 ":"
1 2 3 4 |
int seperatorIndex = usernamePassword.IndexOf(':'); username = usernamePassword.Substring(0, seperatorIndex); password = usernamePassword.Substring(seperatorIndex + 1); |
Remember to put SSL on otherwise everyone can read that data.
Final Code
The final code (in C# 7) may look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public (string,string) getCredentials(HttpContext httpContext) { 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); return (username, password); } else { //Handle what happens if that isn't the case throw new Exception("The authorization header is either empty or isn't Basic."); } } |