1

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.

wst
  • 11,681
  • 1
  • 24
  • 39

1 Answers1

1

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


    }
}
jackmott
  • 1,112
  • 8
  • 16
  • 1
    I'm surprised you recommend setting HttpContext.Current.User to the principal in the OnAuthorize method. Surely this means that Controllers/Actions that are accessible by unauthenticated users and so don't have an Authorize attribute wouldn't have access to the current user if he happens to be authenticated. In classic ASP.NET the place to set HttpContext.Current.User would be in Application_PostAuthenticateRequest - wouldn't it be the same for MVC? – Joe Sep 21 '16 at 20:22
  • Good point, might be better to put it there. I'll think on it and amend my answer. – jackmott Sep 21 '16 at 21:21