Sunday, February 9, 2014

Easy .NET MVC Active Directory Attribute Based Authorization

Active Directory based authorization in .NET is fairly easy. Just throw an attribute on a controller as follows:
[Authorize (Roles="MyAdGroup")]
public class SettingsController : Controller
Sometimes though you do not want to hard code a role in an attribute as you may want to add or remove roles at will. You may also want to change the roles based on whether you are in production or not. I like to keep my Active Directory roles either in a database or a web.config file so that others can change authorization on the fly. In order to have greater control over your authorization roles you need to extend the AuthorizeAttribute and override AuthorizationCore. You also need to override HandleUnauthorizedRequest in order to have a custom redirect page.
    /// <summary>
    /// Redirects to the unauthorized page.
    /// </summary>
    public class AuthorizeSiteRedirect : AuthorizeAttribute
    {
        /// <summary>
        /// Authorization based on roles in web.config.
        /// </summary>
        /// <param name="httpContext" />The http context
        /// <returns>Whether a user is authorized.</returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            //// In this example we use a web.config key.
            //// <add key="Authorization.site" value="Your comma separated Ad Group List"/>
            var roles = ConfigurationManager.AppSettings["Authorization.Site"]
            return roles.Split(',').ToList().Any(role => httpContext.User.IsInRole(role.Trim());
        }

        /// <summary>
        /// Redirects an unauthorized request to the unauthorized page.
        /// </summary>
        /// <param name="filterContext" />The filter context
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        { 
            filterContext.Result = new RedirectResult("~/Unauthorized");
        }
    }
}

You can now add more authorization levels for example an Admin level.
    /// <summary>
    /// Redirects to the unauthorized page.
    /// </summary>
    public class AuthorizeAdminRedirect : AuthorizeSiteRedirect
    {
        /// <summary>
        /// Authorizes a user based on active directory groups.
        /// </summary>
        /// <param name="httpContext" />The http context</param>
        /// <returns>Whether a user is authorized.</returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var roles = ConfigurationManager.AppSettings["Authorization.Site.Admin"]          
            return roles.Split(',').ToList().Any(role => httpContext.User.IsInRole(role.Trim());
        }
    }
}
Now all you have to do is add an attribute to your controller and you are done:
    /// <summary>
    /// Administration page for site settings.
    /// </summary>
    [AuthorizeAdminRedirect]
    public class SettingsController : Controller
Please be aware that when you store you active directory groups in a location like your config file you need to be sure to trim whitespace from your group name. Otherwise httpContext.User.IsInRole will not work accurately. For example if User1 is in group Group1 then User.IsInRole(" Group1") will return false however User.IsInRole("Group1") will return true.

No comments:

Post a Comment