Search code examples
c#asp.netasp.net-membershiphttp-authentication

Combine ASP.NET Membership auth and HTTP auth in MVC application


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.


Solution

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