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.
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:
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.
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==
You've already extracted the header now there are several things you need to do:
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.
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:
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
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 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With