ASP.NET MVC: A utility for testing secured Actions

I have come across a common scenario while developing an ASP.NET MVC application. This being testing Actions that require the user to be authorised and / or requires permissions to execute methods  that are locked down with principal permissions.

Here as an example of a controller with an action that is firstly decorated with the “Authorize” attribute (ASP.NET MVC filter) that requires the user to be in a specified role.

[Authorize(Roles="Client Administrators")]
public ViewResult Edit(int clientId)
{
    return View("Edit");
}

 

While I was writing a test for an Action that needed the user to be Authorized . I   created implementations of the IIdentity and IPrincipal interfaces that I could use to satisfy this requirement. Although this worked, it was not reusable. When you set principle, you should apply it to the current AppDomain instead of the current thread as the every thread created in your AppDomain will have the principal set automatically. Once you have set the principle you cannot apply my than once as it will throw an exception. It is also a problem is you try to reset the principal to null.

To add to matters, is was not long before I needed to satisfy principal permissions. My Principal and Identity implementations needed to be more flexible.

So the answer was to create a utility that firstly set the AppDomain to use my principal implementation and allow each and every test to arrange the state of the principal. For each and every test  I also want to write the minimum amount of code by only writing one line of code.  This line of code would be amongst NBehave and RhinoMocks code that have their own fluent interfaces so I want my line of code to fit in with the fluent style. Below are three ways I want to my utility.

//1
TheCurrentUser.Instance.IsAuthenticated().And.IsInAllRoles();
 
//2
TheCurrentUser.Instance.IsAuthenticated()
    .And.IsInThisRole("System admins")
    .And.IsInThisRole("developers")
    .And.IsInThisRole("power users");
 
//3
TheCurrentUser.Instance.IsNotAuthenticated();

 

So I started to create this utility by placing its into its own assembly. The root object is the “TheCurrentUser” object. Its the only public class in the assembly and is used as  a singleton. It creates and hosts three objects references and sets the IPrincipal implementation to the current AppDomain.

using System;
using System.Security.Principal;
 
namespace RussellEast.Principal.Utility
{
    public class TheCurrentUser
    {
        static readonly TheCurrentUser instance = new TheCurrentUser();
 
        private IPrincipal principal;
        private IAuthenticationOptions options;
        private ISecurityContext context;
 
        private TheCurrentUser()
        {
            BuildObjectGraph();
            SetAppDomainPrincipal();
        }
 
        static TheCurrentUser() { }
 
        public static IAuthenticationOptions Instance
        {
            get { return instance.Options; }
        }
 
        public IAuthenticationOptions Options
        {
            get { return options; }
        }
 
        private void BuildObjectGraph()
        {
            context = new SecurityContext();
            principal = new FakePrincipal(context);
 
            options = AuthenticationOptions.Create(context);
        }
 
        private void SetAppDomainPrincipal()
        {
            AppDomain.CurrentDomain.SetThreadPrincipal(principal);
        }
    }
}

 

The fluent interface uses a context object (that holds the state as its passed around) that is injected into  various objects that are explained below. The context object implements the following interface.

using System.Collections.Generic;
 
namespace RussellEast.Principal.Utility
{
    internal interface ISecurityContext
    {
        bool IsAuthenticated { get; set; }
        bool IsInAllRoles { get; set; }
        List<string> Roles { get; set; }
        void Reset();
    }
}

 

This is the concrete implementation of the ISecurityContext interface.

using System.Collections.Generic;
 
namespace RussellEast.Principal.Utility
{
    class SecurityContext : ISecurityContext
    {
        public bool IsAuthenticated { get; set; }
        public bool IsInAllRoles { get; set; }
        public List<string> Roles { get; set; }
 
        public void Reset()
        {
            IsAuthenticated = false;
            IsInAllRoles = false;
 
            if (Roles != null)
            {
                Roles.Clear();
            }
        }
    }
}

 

Back to the “TheCurrentUser” object, the instance property returns an object that implements the following interface below.

(Although this object is a singleton, the pattern would be to return the singular  instance of the singleton, i have not done this as the singleton does nothing but host objects and be the root object for the fluent interface.)

namespace RussellEast.Principal.Utility
{
    public interface IAuthenticationOptions
    {
        IAuthorisationRouter IsAuthenticated();
        void IsNotAuthenticated();
    }
}

 

My concrete of the above  interface is as follows:

namespace RussellEast.Principal.Utility
{
    class AuthenticationOptions : IAuthenticationOptions
    {
        private readonly IAuthorisationRouter router;
        private readonly ISecurityContext context;
        private AuthenticationOptions(ISecurityContext context, IAuthorisationRouter router)
        {
            this.context = context;
            this.router = router;
        }
 
        public IAuthorisationRouter IsAuthenticated()
        {
            ChangeSecurityState(true);
 
            return router;
        }
 
        public void IsNotAuthenticated()
        {
            ChangeSecurityState(false);
        }
 
        private void ChangeSecurityState(bool isAuthenticated)
        {
            context.Reset();
 
            context.IsAuthenticated = isAuthenticated;
        }
 
        public static IAuthenticationOptions Create(ISecurityContext context)
        {
            var roleAuthorisation = new RoleAuthorisation(context);
            var router = new AuthorisationRouter(roleAuthorisation);
 
            return new AuthenticationOptions(context, router);
        }
    }
}

 

As you can see from the code, the AuthenticationOptions class is passed an instance of the security context and an instance of the IAuthorisationRouter.

The responsibility of this class is to reset the context and set a new authentication value. This class also contains a “Factory Method” that is used to create an instance of this object.

The “IsAuthenticated” method returns the next link in the method chain being the “IAuthorisationRouter”.

namespace RussellEast.Principal.Utility
{
    public interface IAuthorisationRouter
    {
        IRoleAuthorisation And { get; }
    }
}

 

The “IAuthorisationRouter” purpose in life is to provide a linkage in the method chain. Here is the concrete implementation.

namespace RussellEast.Principal.Utility
{
    class AuthorisationRouter : IAuthorisationRouter
    {
        private IRoleAuthorisationController roleAuthorisation;
 
        public AuthorisationRouter(IRoleAuthorisationController roleAuthorisation)
        {
            this.roleAuthorisation = roleAuthorisation;
            this.roleAuthorisation.Router = this;
        }
 
        public IRoleAuthorisation And
        {
            get { return roleAuthorisation; }
        }
    }
}

 

I am using constructor injection as much as possible. It was not so clear cut with this object as the AuthorisationRouter exposes an instance of “RoleAuthorisation” which implies that it has knowledge of it. The “RoleAuthorisation” exposes an instance of the AuthorisationRouter. So both need to know about each other.  I am using interfaces to define the overall fluent interface so I want to keep it clean from any implementation that is needed to wire references to together. So the solution is to create another interface that is only used by a specific consumer  (Interface Segregation Principal). Because I need two instances of different objects that need to know about each other, I have to construct one object first that then inject that into the other object when its be instantiated. Then I use a setter (setter injection) to provide the reference of the second object back to the first object.

namespace RussellEast.Principal.Utility
{
    internal interface IRoleAuthorisationController :
        IRoleAuthorisation, ISettableRouter
    {
    }
}

 

Here is the “ISettableRouter” interface:

namespace RussellEast.Principal.Utility
{
    internal interface ISettableRouter
    {
        IAuthorisationRouter Router { set; }
    }
}

 

Here is the “IRoleAuthorisation” interface.

namespace RussellEast.Principal.Utility
{
    public interface IRoleAuthorisation
    {
        void IsInAllRoles();
        IAuthorisationRouter IsInThisRole(string role);
    }
}

 

I have a concrete class “RoleAuthorisation” that implements the “IRoleAuthorisationController” interface. Its responsibility is to manage the list of roles.

using System.Collections.Generic;
 
namespace RussellEast.Principal.Utility
{
    class RoleAuthorisation : IRoleAuthorisationController
    {
        private IAuthorisationRouter router;
        private readonly ISecurityContext context;
 
        public RoleAuthorisation(ISecurityContext context)
        {
            this.context = context;
        }
 
        public IAuthorisationRouter Router
        {
            set { router = value;  }
        }
 
        public void IsInAllRoles()
        {
            context.IsInAllRoles = true;
        }
 
        public IAuthorisationRouter IsInThisRole(string role)
        {
            if (!string.IsNullOrEmpty(role))
            {
                if (context.Roles == null)
                {
                    context.Roles = new List<string>();
                }
 
                if (!context.Roles.Contains(role))
                {
                    context.Roles.Add(role);
                }
            }
 
            return router;
        }
    }
}

 

That’s all the interfaces and classes needed to build the fluent interface. The last objects needed is the Principal and Identity objects, which reads its values from the context.

using System.Security.Principal;
 
namespace RussellEast.Principal.Utility
{
    class FakePrincipal : GenericPrincipal
    {
        private readonly ISecurityContext context;
 
        public FakePrincipal(ISecurityContext context) : base(new FakeIdentity(context), null)
        {
            this.context = context;
        }
 
        public override bool IsInRole(string role)
        {
            if (context.IsAuthenticated)
            {
                return context.IsInAllRoles ? true : context.Roles.Contains(role);
            }
 
            return false;
        }
 
        class FakeIdentity : GenericIdentity
        {
            private readonly ISecurityContext context;
 
            public FakeIdentity(ISecurityContext context) : base("Fake user")
            {
                this.context = context;
            }
 
            public override bool IsAuthenticated
            {
                get { return context.IsAuthenticated; }
            }
         }
    }
}

 

Although a lot of code is written for the fluent interface which took two hours to build from scratch, I have a very flexible utility that I know I am going to use a lot and not just with ASP.NET MVC. The only refactoring that I want to perform is to change the name of some of the interfaces as I feel that they could be better described. To finish this post, here is an example using this utility in a unit test.

 

 
        [Specification]
        public void Should_be_able_to_edit_a_client()
        {
            ViewResult result = null;
 
            story.WithScenario("editing a client")
                .Given("an instance of the controller", () => controller.ShouldNotBeNull())
                .And("the current user belongs to the 'client administrators' role", () =>
                {
                    TheCurrentUser.Instance.IsAuthenticated()
                        .And.IsInThisRole("Client Administrators");
 
                    //NOTE: these two lines are not needed, just  validating the utility.
                    Thread.CurrentPrincipal.Identity.IsAuthenticated.ShouldBeTrue();
                    Thread.CurrentPrincipal.IsInRole("Client Administrators").ShouldBeTrue();
                })
                .When("the Edit action is invoked", () =>
                {
                    result = controller.Edit(1) as ViewResult;
                })
                .Then("verify that the user is directed to the right view", () =>
                {
                    result.AssertViewRendered().ForView("Edit");
                });
 
        }

 

For a better understanding of the unit test above, please read this post

Advertisements

8 responses to “ASP.NET MVC: A utility for testing secured Actions

  1. Pingback: ASP.NET MVC Archived Blog Posts, Page 1

  2. Pingback: DotNetShoutout

  3. Russell, I copied your code, but it doesn’t change the IsAuthenticated property during the test. Maybe it has to do with me using nunit. Did you had any problems during your tests?

    Thanks.

    • @jesus, thanks for that, i am still using an older version of nunit 2.5 and i was unaware of this issue in this new version.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s