RealWorldDevelopers
4/30/2016 - 8:59 PM

Active Directory in MVC

Active Directory in MVC

<?xml version="1.0"?>

<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="ExtTransfersAdmin.Views.BaseViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

  <appSettings>
    <add key="webpages:Enabled" value="false" />
  </appSettings>

  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
    </httpHandlers>

    <!--
        Enabling request validation in view pages would cause validation to occur
        after the input has already been processed by the controller. By default
        MVC performs request validation before a controller processes the input.
        To change this behavior apply the ValidateInputAttribute to a
        controller or action.
    -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />

    <handlers>
      <remove name="BlockViewHandler"/>
      <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>

using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;


namespace ExtTransfersAdmin
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            AutoMapperConfig.RegisterMappings();

        }
    }
}

using System.Web.Mvc;
using ExtTransfersAdmin.Filters;

namespace ExtTransfersAdmin
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new AuthorizationFilter());
        }
    }
}
using System.DirectoryServices.AccountManagement;
using System.Security.Principal;

namespace ExtTransfersAdmin.Secuirty
{
    public class CustomPrincipal : IPrincipal
    {
        public CustomPrincipal(IPrincipal principal, UserPrincipal userPriciple)
        {
            _userPrincipal = userPriciple;
            _principal = principal;
        }

        private readonly IPrincipal _principal;
        private readonly UserPrincipal _userPrincipal;

        public bool IsInRole(string role)
        {
            return _principal.IsInRole(role);
        }

        public IIdentity Identity
        {
            get { return _principal.Identity; }
        }

        /// <summary>
        /// Gets the Full Name for this account.
        /// </summary>
        public string FullName
        {
            get { return _userPrincipal.Name; }
        }

        /// <summary>
        /// Gets the omain for this account.
        /// </summary>
        public string Domain
        {
            get
            {
                var s = Identity.Name;
                var stop = s.IndexOf("\\", System.StringComparison.Ordinal);
                return (stop > -1) ? s.Substring(0, stop) : string.Empty;
            }
        }

        /// <summary>
        /// Gets the Login for this account.
        /// </summary>
        public string Login
        {
            get
            {
                var s = Identity.Name;
                var stop = s.IndexOf("\\", System.StringComparison.Ordinal);
                return (stop > -1) ? s.Substring(stop + 1, s.Length - stop - 1) : string.Empty;
            }
        }


        /// <summary>
        /// Gets the Display Name for this account.
        /// </summary>
        public string DisplayName
        {
            get { return _userPrincipal.DisplayName; }
        }


        /// <summary>
        /// Gets the e-mail address for this account.
        /// </summary>
        public string EmailAddress
        {
            get { return _userPrincipal.EmailAddress; }
        }


        /// <summary>
        ///  Gets the employee ID for this user principal.
        /// </summary>
        public string EmployeeId
        {
            get { return _userPrincipal.EmployeeId; }
        }

        /// <summary>
        /// Gets the given name for the user principal.
        /// </summary>
        public string GivenName { get { return _userPrincipal.GivenName; } }

        /// <summary>
        ///  Gets the middle name for the user principal.
        /// </summary>
        public string MiddleName { get { return _userPrincipal.MiddleName; } }

        /// <summary>
        /// Gets the surname for the user principal.
        /// </summary>
        public string Surname { get { return _userPrincipal.Surname; } }


        /// <summary>
        /// Gets the voice telephone number for the user principal.
        /// </summary>
        public string VoiceTelephoneNumber { get { return _userPrincipal.VoiceTelephoneNumber; } }

    }
}
using System;
using System.Web.Mvc;

namespace ExtTransfersAdmin.Controllers
{
    public static class ControllerExtension
    {
        public static string MakeActive(this UrlHelper urlHelper, string controller)
        {
            var result = "active";

            var controllerName = urlHelper.RequestContext.RouteData.Values["controller"].ToString();

            if (!controllerName.Equals(controller, StringComparison.OrdinalIgnoreCase))
            {
                result = null;
            }

            return result;
        }
    }
}

using System.Web.Mvc;
using ExtTransfersAdmin.Secuirty;

namespace ExtTransfersAdmin.Views
{
    public abstract class BaseViewPage : WebViewPage
    {
        public virtual new CustomPrincipal User
        {
            get { return base.User as CustomPrincipal; }
        }
    }

    public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
    {
        public virtual new CustomPrincipal User
        {
            get { return base.User as CustomPrincipal; }
        }
    }
}

using System.Web.Mvc;
using ExtTransfersAdmin.Secuirty;

namespace ExtTransfersAdmin.Controllers
{
    public class BaseController : Controller
    {
        protected virtual new CustomPrincipal User
        {
            get { return HttpContext.User as CustomPrincipal; }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.DirectoryServices.AccountManagement;
using System.Web.Routing;
using System.Web.Security;
using ExtTransfersAdmin.Secuirty;
using Framework.Common.Utils;
using Framework.Logging;


namespace ExtTransfersAdmin.Filters
{
    public class AuthorizationFilter : AuthorizeAttribute
    {
        private const string IsAuthorized = "isAuthorized";
        public string RedirectUrl = "~/Message/DenyAccess";

        /// <summary>
        /// Authentication
        /// </summary>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            bool isAuthorized;
            try
            {
                isAuthorized = base.AuthorizeCore(httpContext);

                if (isAuthorized)
                {
                    var routeData = ((MvcHandler)httpContext.Handler).RequestContext.RouteData;
                    var roles = GetAuthorizedRoles(routeData);
                    if (roles != null)
                    {
                        var provider = new WindowsTokenRoleProvider();
                        isAuthorized = (roles.Any(role => provider.IsUserInRole(httpContext.User.Identity.Name, role)));
                    }
                }

                // for testing only remove or comment out 
                //if (ConfigHelper.AppSettings("Environment").StartsWith("Dev"))
                //    isAuthorized = true;

                //  handle if already in context
                var items = httpContext.Items;
                if (items.Contains(IsAuthorized))
                    httpContext.Items.Remove(IsAuthorized);

                httpContext.Items.Add(IsAuthorized, isAuthorized);
            }
            catch (Exception ex)
            {
                Logger.Instance.Error(ex, "Authorize Core", new Dictionary<string, object>
                    {
                        { "user", httpContext.User.Identity.Name }
                    });
                throw;
            }
            return isAuthorized;
        }

        /// <summary>
        /// Authorization
        /// </summary>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            // authenticated
            base.OnAuthorization(filterContext);

            try
            {
                // check if authorized
                var isAuthorized = filterContext.HttpContext.Items[IsAuthorized] != null &&
                    Convert.ToBoolean(filterContext.HttpContext.Items[IsAuthorized]);

                Logger.Instance.Info("User Authentication", "On Authorization", new Dictionary<string, object>
                    {
                        { "user", filterContext.RequestContext.HttpContext.User.Identity.Name },
                        {"isAuthorized",isAuthorized}
                    });

                // redirect to deny access page if not authorized
                if (!isAuthorized && filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
                    filterContext.RequestContext.HttpContext.Response.Redirect(RedirectUrl);

                // build custom user for extended user information throughout the app
                var principalContext = new PrincipalContext(ContextType.Domain);
                var principal = filterContext.RequestContext.HttpContext.User;
                var identity = principal.Identity;

                var userPrincipal = UserPrincipal.FindByIdentity(principalContext, identity.Name);
                var newCustomePrincipal = new CustomPrincipal(principal, userPrincipal);
                HttpContext.Current.User = newCustomePrincipal;
                Thread.CurrentPrincipal = newCustomePrincipal;
            }
            catch (Exception ex)
            {
                Logger.Instance.Error(ex, "On Authorization", new Dictionary<string, object>
                    {
                        { "user", filterContext.RequestContext.HttpContext.User.Identity.Name  }
                    });
                throw;
            }

        }

        private static IEnumerable<string> GetAuthorizedRoles(RouteData routeData)
        {

            var controller = routeData.Values["controller"].ToString();
            // var action = routeData.Values["action"].ToString();
            string appSettings = null;
            switch (controller.ToLower())
            {
                case "home":
                    appSettings = ConfigHelper.AppSettings("ViewAccountsRoleName");
                    break;
                case "manageaccounts":
                    appSettings = ConfigHelper.AppSettings("ManageAccountsRoleName");
                    break;
                case "holidaycalendar":
                    appSettings = ConfigHelper.AppSettings("HolidayRoleName");
                    break;
                case "routing":
                    appSettings = ConfigHelper.AppSettings("RoutingRoleName");
                    break;
            }

            if (string.IsNullOrWhiteSpace(appSettings))
            {
                Logger.Instance.Warn("Missing AD groups in Web.config for Roles");
                return null;
            }
            return appSettings.Split(',');
        }

    }
}