I would like to add basic HTTP authorization to entire site that uses forms authentication for some protected pages. The idea is to present development stage of the portal to the client so he could play with it, but to secure the entire site with additional simple login and password on HTTP level so no one else could access it. Classic tag in web.config is not enough here because the portal could use forms authentication (with user registration) as a part of its functionality. I would like to authorize user by HTTP prior to forms authentication which can happen later.
The HTTP level authorization should have logins and password configured by administrator (i.e in a text file).
Would it be possible to achieve this functionality by custom http module?
UPDATE:
The idea is to create configuration-level way of securing application. Forms Authentication is not en option here because handling different account types and roles would require changes in the application.
I've already resolved this issue with simple custom module that tests HTTP Authorization header and response with HTTP 401. This module can be attached to any website via Web.Config
SOLUTION:
Module class:
public class BasicAuthModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(this.HttpApplicationBeginRequest);
}
private void HttpApplicationBeginRequest(object sender, EventArgs e)
{
var request = HttpContext.Current.Request;
var response = HttpContext.Current.Response;
string authHeader = request.Headers["Authorization"];
if (string.IsNullOrEmpty(authHeader))
{
this.RequireAuthorization(response);
}
else
{
string authType = authHeader.Split(' ').First();
string authData = authHeader.Split(' ').Last();
if (authType.ToLower() == "basic")
{
byte[] bytes = Convert.FromBase64String(authData);
string plainText = Encoding.UTF8.GetString(bytes);
string login = plainText.Split(':').First();
string password = plainText.Split(':').Last();
if (!this.Validate(login, password))
{
this.DenyAccess(response);
}
}
else
{
this.DenyAccess(response);
}
}
}
private bool Validate(string login, string password)
{
return (login == ConfigurationManager.AppSettings["AuthLogin"]) && (password == ConfigurationManager.AppSettings["AuthPwd"]);
}
private void RequireAuthorization(HttpResponse response)
{
response.AddHeader("WWW-Authenticate", "Basic realm=\"stage\"");
response.StatusCode = 401;
response.Status = "401 Authorization Required";
response.ContentType = "text/html";
response.End();
}
private void DenyAccess(HttpResponse response)
{
response.AddHeader("WWW-Authenticate", "Basic realm=\"stage\"")
response.StatusCode = 401;
response.Status = "401 Authorization Required";
response.ContentType = "text/html";
response.End();
}
}
In web.config:
<modules runAllManagedModulesForAllRequests="true">
...
<add name="BasicAuthModule" type="MyNamespace.BasicAuthModule, MyNamespace.Module"/>
</modules>