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:

public ActionResult DeactivateMembership(Membership model)
 {
    // your business logic here
    return View("DeactivateMembership", model);
 }

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

[AuthorizeAD(Groups = Constants.CSgroup)]</strong>
 public ActionResult DeactivateMembership(Membership model)
 {
    // your business logic here
    return View("DeactivateMembership", model);
 }

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:

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

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:

public static class Constants
    {
        /// <summary>
        /// CS - Customer support and customer support leads
        /// </summary>
        public const string CSgroup = "csr, csr_leads";
}

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:

// Only give access to a group
[AuthorizeAD(Groups = "yourADgroup")]

</strong>
<strong>// Give access to a group and a user
[AuthorizeAD(Groups = "yourADgroup", Users = "someuser")]</strong>
<strong>
// Give access to a Role
[AuthorizeAD(Roles = "Admin")]

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.

 

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

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

    Like

  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!

    Like

    1. Ricardo Avatar

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

      Like

  3. Pim Avatar
    Pim

    Thanks so much!

    Like

  4. Patrick Desjardins (@mrdesjardins) Avatar

    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.

    Like

    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.

      Like

  5. gabrielgramajo Avatar

    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.

    Like

    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.

      Like

  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?

    Like

  7. Thilo Langbein Avatar
    Thilo Langbein

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

    Like

  8. Patrick Avatar
    Patrick

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

    Like

  9. sada Avatar

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

    Like

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

I’m Ricardo

Photo of Ricardo

I enjoy coding and working with great people, as well as taking photographs, writing, reading, and traveling whenever possible.

Let’s connect

Create a website or blog at WordPress.com