How to use Active Directory groups to restrict access to controller actions in ASP.NET MVC and make your application even more secure!

It’s been a year and one of the most popular posts in this blog still today is How To: Secure your ASP.NET MVC application and use Active Directory as the Membership Provider. In that post I promised to write about how to use Active Directory groups to restrict access to controller actions to make your application even more secure by consolidating access based in already defined groups in Active Directory (AD). I finally got to it and here it is.

Remember that if you are not already using Active Directory as your membership provider in your application, you need to first follow the steps described in the first post mentioned above.

In a business, the use of Active Directory to organize user and computer accounts is very common. When we create new web applications for that business it is likely that we want to have some access control to certain areas of the application. For example, let’s say that you have a web application that helps accounting and customer support get details about a certain customer such as reports, invoice details, account information, etc… In such application there is a good chance that accounting and customer service employees will have different access to different areas in the application.

The Example

Here is an example of what such a task will look like in the controller of your MVC application:
[code language=”csharp”]
public ActionResult DeactivateMembership(Membership model)
{
// your business logic here
return View(“DeactivateMembership”, model);
}
[/code]
And here is what is going to look like with an attribute that will only allow users in the customer service group to execute such task
[code language=”csharp”]
[AuthorizeAD(Groups = Constants.CSgroup)]
public ActionResult DeactivateMembership(Membership model)
{
// your business logic here
return View(“DeactivateMembership”, model);
}
[/code]

The custom AuthorizeAD attribute

The custom attribute labeled AuthorizeAD is what makes this happen, below is the declaration of this custom attribute that access Active Directory to determine if an specific user or group within AD has access to a defined controller action:
[code language=”csharp”]
namespace Application.Filters
{
public class AuthorizeADAttribute : AuthorizeAttribute
{
   public string Groups { get; set; }
   protected override bool AuthorizeCore(HttpContextBase httpContext)
   {
      if (base.AuthorizeCore(httpContext))
       {
          /* Return true immediately if the authorization is not 
          locked down to any particular AD group */
          if (String.IsNullOrEmpty(Groups))
               return true;

// Get the AD groups
var groups = Groups.Split(‘,’).ToList();

// Verify that the user is in the given AD group (if any)
      var context = new PrincipalContext(
ContextType.Domain,
“yourdomainname”);

var userPrincipal = UserPrincipal.FindByIdentity(
context,
                                  IdentityType.SamAccountName,
                                  httpContext.User.Identity.Name);

foreach (var group in groups)
    if (userPrincipal.IsMemberOf(context,
IdentityType.Name,
group))
          return true;
       }
         return false;
}

protected override void HandleUnauthorizedRequest(
AuthorizationContext filterContext)
  {
      if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
             var result = new ViewResult();
             result.ViewName = “NotAuthorized”;
             result.MasterName = “_Layout”;
             filterContext.Result = result;
        }
        else
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}
[/code]
The code above overrides the AuthorizeCore call which allow us to customize the authorization check so we can use the Active Directory in our domain.

The implementation

To limit access to controller actions you will use the new custom attribute like this:

[AuthorizeAD(Groups = Constants.CSgroup)]

Where Constant.CSGroup is just a constant value I created that translates to the actual name of the AD group. This can also be used to aggregate two or more AD groups as one value if needed. In the class below I set the value of CSgroup to be the name of two different AD groups in my domain, the csr group and csr_leads group:
[code language=”csharp”]
public static class Constants
    {
        ///

        /// CS – Customer support and customer support leads
        ///

        public const string CSgroup = “csr, csr_leads”;
}
[/code]
If you don’t need to do this then you can use the custom attribute by simply providing the name of your AD group, a user name or the name of a Role within your Active Directory:
[code language=”csharp”]
// Only give access to a group
[AuthorizeAD(Groups = “yourADgroup”)]


// Give access to a group and a user
[AuthorizeAD(Groups = “yourADgroup”, Users = “someuser”)]


// Give access to a Role
[AuthorizeAD(Roles = “Admin”)]
[/code]
That’s it! Hope this is helpful for you and as always, if you have a recommendation, a comment or question please use the comment’s section below.

 


Comments

  1. […] this post I show how to use Active Directory groups to restrict access to controller actions and make your […]

  2. Jesse Avatar
    Jesse

    Great post.

    Where do I put the code for the AuthorizeADAttribute class? Does it have to go in a particular file? I’ve never added an application filter so not sure where that goes.

    Thanks!

    1. Hi Jesse, in my example I created this class inside the Controllers folder with the namespace Application.Filters

  3. Thanks so much!

  4. Hello. You do not need to have a custom Authorize attribute to use Active Directory. It’s possible by defining inside the web.config a role provider to AD and it will works with the Authorize attribute. Have a nice day.

    1. Rajendra Avatar
      Rajendra

      This code worked perfectly. I am wondering how this can be done in web.config using authorize attribute. Can you please post the code.

  5. Is there any sort of cache that prevents new groups to be immediately visible to the ad class ? We have problems with some users that despite being in a group included in the property they are not able to access the controller.

    1. ricardodsanchez Avatar
      ricardodsanchez

      Gabriel – It is very possible that your Active Directory objects are being cached – read this: https://technet.microsoft.com/en-us/library/cc747586(v=ws.10).aspx – without knowing how things are setup in your domain is hard to tell if that is causing the behavior you are seeing or not.

  6. David Avatar
    David

    I am a bit of a beginner and have been thrown in to this MVC AD situation. I don’t suppose you might be kind enough to put a bare bones example solution somewhere with a few more comments for someone who is still learning C# and MVC? I realize you might not have time for this but no harm in asking. Thanks

    On another note can you authorize against active directory and a Db at the same time. This might seem crazy but not all users will be in AD in some scenarios that will involve external requests?

  7. Thilo Langbein Avatar
    Thilo Langbein

    How is the performance? Checking memberships an every call takes some time. What about caching?

  8. Patrick Avatar
    Patrick

    can you sho me how can I show all the field from the AD?
    Thank you

  9. i want ask u… why in my project always return false

Leave a Reply

Your email address will not be published. Required fields are marked *