I have an existing ASP.NET MVC 4.5 application that authenticates users via .NET Membership. I would also like to allow optional basic HTTP authentication in lieu of Membership for use by DevOps-type scripts (cache warming, testing, etc.) that can't login using a browser.
Ideally, the credentials used for HTTP Auth would be the same ones in Membership, but it's not critical. The only critical thing is that website users would not prompted for HTTP credentials if they're not provided.
One way is to override the OnAuthorize
method of AuthorizeAttribute
, check for the existence of an Authorization header, and if you find it, extract and validate the credentials, and then create the IPrincipal
by hand. Otherwise, call the base.OnAuthorization
so that the usual .NET membership things happen.
source:
public class RoleAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
bool basicValidated = false;
var req = filterContext.HttpContext.Request;
var auth = req.Headers["Authorization"];
if (!string.IsNullOrEmpty(auth))
{
var cred = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
var userName = cred[0];
var pass = cred[1];
var membership = new AccountMembershipService();
basicValidated = membership.ValidateUser(userName, pass);
if (!basicValidated)
{
base.OnAuthorization(filterContext);
}
else
{
var roles = System.Web.Security.Roles.GetRolesForUser(userName);
IPrincipal principal = new GenericPrincipal(
new GenericIdentity(userName),roles);
Thread.CurrentPrincipal = principal;
System.Web.HttpContext.Current.User = principal;
}
} else
{
base.OnAuthorization(filterContext);
}
}
}