Setting Up FluentSecurity to Use Ninject for Dependency Resolution

A couple of months ago, I blogged about how to secure an ASP.NET MVC application using the excellent library FluentSecurity. I described how to install and configure FluentSecurity; however, I didn’t go into detail about how exactly you would set up a dependency injection framework which is necessary for FluentSecurity to resolve its policy violation handlers.

In this post, you’re going to read about how to use Ninject to register and resolve concrete implementations for a custom FluentSecurity policy violation handler. I assume that you have at least a basic understanding of the concept of dependency injection (or inversion of control). If that shouldn’t be the case, I recommend you read the Wikipedia article on dependency injection before diving into this post.

Integrating Ninject into Your ASP.NET MVC Application

Given that you already have an ASP.NET MVC application with FluentSecurity set up, install the NuGet package Ninject.MVC3 to integrate Ninject:

install-package Ninject.MVC3

After you have installed the above package, you will find a newly created file called NinjectWebCommon.cs within your application’s App_Start folder. This is where you configure Ninject and register the services you want resolved.

Introducing FluentSecurity to Ninject

FluentSecurity doesn’t magically know that it’s supposed to use Ninject to resolve services. To make use of dependency injection, you have to call one of the following two overloads of the ResolveServicesUsing method in FluentSecurity’s configuration section:

  1. ResolveServicesUsing(Func<Type, IEnumerable<object> servicesLocator)
  2. ResolveServicesUsing(ISecurityServiceLocator securityServiceLocator)

The first overload requires you to pass it a method pointer for its servicesLocator parameter. That method you point to has to accept a single Type parameter and return a collection of services that are registered for that specific type. (You can optionally pass in a second parameter that resolves a Type and returns a single service.)

The second overload accepts an instance of a class that implements the interface ISecurityServiceLocator. That interface specifies two methods, Resolve and ResolveAll, which have the same signature as the method pointers used by the parameters of the first overload.

You’re free to decide which overload you want to use to tell FluentSecurity where to retrieve the required services from. In the end, both provide the same functionality, so which one you use is just a matter of personal preference: You can either implement an interface specifying the methods necessary for resolving services, or you can directly pass the pointers to those methods yourself.

Implementing a Custom Policy Violation Handler

If a policy is violated, FluentSecurity tries to resolve a policy violation handler that determines what to do. Let’s take the DenyAnonymousAccessPolicy, for example. If an unauthenticated user requests an action that is secured by that policy, FluentSecurity denies access to the requested action because the policy is violated. It then looks for an appropriate policy violation handler which knows how to handle the specific violation. To be a match for the DenyAnonymousAccessPolicy, the violation handler has to meet the following criteria:

  1. Its class name has to be DenyAnonymousAccessPolicyViolationHandler.
  2. It has to implement IPolicyViolationHandler.
  3. It has to be registered with the used dependency injection framework.

Please note that the first criterion isn’t required in version 2.0 of FluentSecurity. If you register a policy violation handler called DefaultPolicyViolationHandler, FluentSecurity will use that handler as a fallback if it cannot find a more specific handler for the policy violation.

A possible policy violation handler implementation for the DenyAnonymousAccessPolicy could look like the following:

public class DenyAnonymousAccessPolicyViolationHandler : IPolicyViolationHandler
{
    public ActionResult Handle(PolicyViolationException exception)
    {
        return new RedirectToRouteResult("SignIn", routeValues: null);
    }
}

Please note that you'll have to register a route named SignIn for the handler to function correctly:

routes.MapRoute("SignIn", "SignIn", new { controller = "Account", action = "SignIn" });

It's up to you what type of ActionResult you want to return. Instead of redirecting to the SignIn action, you could also return a special view for unauthorized access, for example.

Registering a Policy Violation Handler

Before we dive into the FluentSecurity specifics, let’s have a look at how you register services with Ninject in general.

Open the NinjectWebCommon.cs file and locate the RegisterServices method. This is where you register the services for your application. You can also do some advanced stuff in there, such as loading Ninject modules. However, that’s a topic on its own and won’t be covered in this post.

Ninject provides a fluent syntax to bind interfaces to concrete implementations. A so-called kernel holds the services binding information. The binding syntax is very clean and reads nicely:

kernel.Bind<T>().To<TImplementation>();

To apply the interface binding to your custom policy validation handler scenario, you can bind the IPolicyViolationHandler interface to your DenyAnonymousAccessPolicyViolationHandler as follows:

kernel.Bind<IPolicyViolationHandler>().To<DenyAnonymousAccessPolicyViolationHandler>();

This solution works fine, but it has a catch: For each new policy violation handler that you create, you will have to bind the IPolicyViolationHandler interface to the newly created handler to register it with Ninject. That’ll become tedious work, and you’ll have to remember to update your bindings every time. Plus, manually registering violation handlers doesn’t follow the Open/Closed Principle. You can read more about why that's bad in the paper The Open-Closed Principle.

Enough with Poor Man’s Violation Handler Binding™ — let’s take a look at a better solution.

Registering All Policy Violation Handlers in an Entire Assembly

A more effective approach to register policy violation handlers is to scan the current assembly for all types implementing IPolicyViolationHandler and to register all of them at once. The code for that is fairly straightforward:

private static void BindPolicyViolationHandlers(IKernel kernel)
{
    Type handlerType = typeof(IPolicyViolationHandler);
    Func<Type, bool> typeIsHandler = handlerType.IsAssignableFrom;

    IEnumerable<Type> assemblyTypes = Assembly.GetExecutingAssembly().GetTypes();
    IEnumerable<Type> handlersInAssembly = assemblyTypes.Where(typeIsHandler);

    foreach (Type handler in handlersInAssembly)
    {
        kernel.Bind<IPolicyViolationHandler>().To(handler);
    }
}

You can simply call the above method from the RegisterServices method like that:

BindPolicyViolationHandlers(kernel);

With that configuration in place, you can now add new policy violation handlers to your application without any further manual work, such as adding Ninject service bindings. Just keep in mind to name new policy violation handlers according to the naming convention <PolicyName>ViolationHandler and to implement the interface IPolicyViolationHandler.

Further Resources

Use the coupon code LAUNCHDAY for $10 off!

Learn React

2 Comments

ehm

I lose you on the very fist step ...... don't tell tutorial readers (US) method HEADERS, please tell us concrete calls and the places where to put them.

ehm

Ok, I have it now partially thanks to your guide. Thanks! Still, I'm amazed that I had to go through all of this just because I want users redirected to a proper page when security violations occur.