Sergey Akopov

Perpetual adventurer and purveyor of awesomeness.

Tamper-proof hidden fields in ASP.NET MVC

A common practice a lot of web developers employ is storing random referential data in hidden fields in the views. More often than not, this includes identifiers to database records. Any relatively knowledgeable user can alter these fields with an in-browser DOM editor. Hence, a good rule of thumb is to always validate every piece of data received from the user and make sure they're persisting all data as they should.

What I'd like to show is a simple way to help mitigate the tampering of the data in hidden fields by generating an encrypted token of the original value and then validating that the value still matches the token when it's submitted by the user. This works very similar to the AntiForgeryToken mechanism already implemented in MVC. Just to make it clear, this trick doesn't alleviate the need for data validation. It is merely a way to provide extra layer of protection.

Let's start by creating a new set of HTML helpers to spin-up protected hidden fields. Each helper will generate two hidden fields - one with the original value and one with the encrypted Base64 string of the original value (the token). If the attacker tries to modify a protected hidden field, they'd also have to provide the correct encrypted token.

public static class HtmlExtensions
{
    public static MvcHtmlString SecureHidden(this HtmlHelper htmlHelper, string name)
    {
        return SecureHidden(htmlHelper, name, value: null, htmlAttributes: null);
    }

    public static MvcHtmlString SecureHidden(this HtmlHelper htmlHelper, string name, object value)
    {
        return SecureHidden(htmlHelper, name, value, htmlAttributes: null);
    }

    public static MvcHtmlString SecureHidden(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes)
    {
        return SecureHidden(htmlHelper, name, value, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureHidden(
        this HtmlHelper htmlHelper,
        string name,
        object value,
        IDictionary<string, object> htmlAttributes)
    {
        return SecureHiddenHelper(htmlHelper, value: value, name: name, htmlAttributes: htmlAttributes);
    }

    public static MvcHtmlString SecureHiddenFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression)
    {
        return SecureHiddenFor(htmlHelper, expression, null);
    }

    public static MvcHtmlString SecureHiddenFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        object htmlAttributes)
    {
        return SecureHiddenFor(htmlHelper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureHiddenFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        IDictionary<string, object> htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

        return SecureHiddenHelper(htmlHelper, metadata.Model, ExpressionHelper.GetExpressionText(expression), htmlAttributes);
    }

    public static MvcHtmlString DisableIf(this MvcHtmlString instance, Func<bool> expression)
    {
        const string Disabled = "\"disabled\"";

        if (expression.Invoke())
        {
            var html = instance.ToString();
            html = html.Insert(html.IndexOf(">", StringComparison.Ordinal), " disabled= " + Disabled);
            return new MvcHtmlString(html);
        }

        return instance;
    }

    private static MvcHtmlString SecureHiddenHelper(
        HtmlHelper htmlHelper,
        object value,
        string name,
        IDictionary<string, object> htmlAttributes)
    {
        var binaryValue = value as Binary;

        if (binaryValue != null)
        {
            value = binaryValue.ToArray();
        }

        var byteArrayValue = value as byte[];

        if (byteArrayValue != null)
        {
            value = Convert.ToBase64String(byteArrayValue);
        }

        return InputHelper(htmlHelper, name, value, setId: true, format: null, htmlAttributes: htmlAttributes);
    }

    private static MvcHtmlString InputHelper(
        HtmlHelper htmlHelper,
        string name,
        object value,
        bool setId,
        string format,
        IDictionary<string, object> htmlAttributes)
    {
        var fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

        if (string.IsNullOrEmpty(fullName))
        {
            throw new ArgumentException("name");
        }

        var inputItemBuilder = new StringBuilder();

        var hiddenInput = new TagBuilder("input");
        hiddenInput.MergeAttributes(htmlAttributes);
        hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
        hiddenInput.MergeAttribute("name", fullName, true);
        hiddenInput.MergeAttribute("value", htmlHelper.FormatValue(value, format));

        var hiddenInputHash = new TagBuilder("input");
        hiddenInputHash.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
        hiddenInputHash.MergeAttribute("name", string.Format("__{0}Token", fullName), true);

        var identity = htmlHelper.ViewContext.HttpContext.User.Identity;

        if (!string.IsNullOrEmpty(identity.Name))
        {
            value = string.Format("{0}_{1}", identity.Name, value);
        }

        var encodedValue = Encoding.Unicode.GetBytes(htmlHelper.FormatValue(value, format));

        hiddenInputHash.MergeAttribute(
            "value",
            Convert.ToBase64String(MachineKey.Protect(encodedValue, "Protected Hidden Input Token")));

        if (setId)
        {
            hiddenInput.GenerateId(fullName);
            hiddenInputHash.GenerateId(string.Format("__{0}Token", fullName));
        }

        inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
        inputItemBuilder.Append(hiddenInputHash.ToString(TagRenderMode.SelfClosing));

        return MvcHtmlString.Create(inputItemBuilder.ToString());
    }
}

The class above provides multiple overloads of SecureHidden and SecureHiddenFor, which allows the consumer to generate a protected hidden for a property of a view model or an arbitrary form field name and value. The InputHelper method does all of the grunt work. I'm using MachineKey for all encryption purposes. This is the same encryption mechanism used internally by the framework to encrypt authentication cookies and view state.

In addition, I'm relying on the current user identity to provide user-specific encryption by combining username with the original value. This makes it more difficult to use the encrypted token across accounts. However, this limits the use of the helper to authenticated scenarious. You could probably use session ID here or something similar. In fact, if I remember correctly, the AntiForgeryToken implementation uses session for this purpose.

The next step is to register these helpers with Razor. Head on over to your Views folder and open Web.config. In the <namespace> node of <system.web.webPages.razor> reference the namespace containing your new helpers. You should now be able to use your helpers as you would any other native helper in MVC.

@Html.SecureHiddenFor(model => model.SomeProperty)

The above should result in generated HTML similar to the one below.

<input id="SomeProperty" name="SomeProperty" type="hidden" value="I love lamp">
<input name="__SomePropertyToken" type="hidden" value="zqb7MIL2Y5F3jL96ncdSZOmetL8g8RAWZP8Y/w/jUAKJ89GcUViRWOZ/XtQhtICMFZb4sQtZLOpqK/WyC0TFP0B6r+3nObFGDjb0U459yzQbadC4+DLIsTmhyYeT+ZT+bnW1AEP2fgVyXXSduYIf5vns7g9nhRWTgJo8xF6NQyT6kNgyl5puq+BYc8dfhMXn">

Finally, we need to validate all protected hidden fields. This is done by implementing a filter attribute for controller actions, which would specify the names of the hidden fields which need to be validated. The validation process is very trivial. We'll just decrypt the token and compare it to the current username and hidden field value combination. If they do not match we'll throw an exception. Otherwise everything continues as it should.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ValidateSecureHiddenInputsAttribute : FilterAttribute, IAuthorizationFilter
{
    private readonly string[] properties;

    public ValidateSecureHiddenInputsAttribute(params string[] properties)
    {
        if (properties == null || !properties.Any())
        {
            throw new ArgumentException("properties");
        }

        this.properties = properties;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        this.properties.ToList().ForEach(property => Validate(filterContext, property));
    }

    private static void Validate(AuthorizationContext filterContext, string property)
    {
        var protectedValue = filterContext.HttpContext.Request.Form[string.Format("__{0}Token", property)];
        var decodedValue = Convert.FromBase64String(protectedValue);

        var decryptedValue = MachineKey.Unprotect(decodedValue, "Protected Hidden Input Token");

        if (decryptedValue == null)
        {
            throw new HttpSecureHiddenInputException("A required security token was not supplied or was invalid.");
        }

        protectedValue = Encoding.Unicode.GetString(decryptedValue);

        var originalValue = filterContext.HttpContext.Request.Form[property];

        var identity = filterContext.HttpContext.User.Identity;

        if (!string.IsNullOrEmpty(identity.Name))
        {
            originalValue = string.Format("{0}_{1}", identity.Name, originalValue);
        }

        if (!protectedValue.Equals(originalValue))
        {
            throw new HttpSecureHiddenInputException("A required security token was not supplied or was invalid.");
        }
    }
}

public class HttpSecureHiddenInputException : Exception
{
    public HttpSecureHiddenInputException(string message) : base(message)
    {
    }
}

With all pieces in place and assuming you created a protected hidden field...

@Html.SecureHiddenFor(model => model.SomeProperty)

You can validate it by decorating your target action.

[ValidateSecureHiddenInputs("SomeProperty")]
public ActionResult Index(MyViewModel model)
{
    return View();
}

Happy coding!

Discuss »

How I do dependency injection

It seems that dependency injection (DI) as software development pattern has become the standard for many open source projects and software companies. Indeed, if you practice any kind of tiered development and employ test-driven practices, DI is likely a great direction for your projects.

When done right, DI allows developers to rather effortlessly extrapolate a complex design into well-defined and easily consumable modules. It gives the flexibility in how objects are interconnected thus allowing greater configuration facility for different modes of operation of your application. Having said all of this, the real trouble of DI is that in most cases the concept behind it is misunderstood and it becomes a major factor of absue.

Here is just a few problems with dependency injection, which I come across time and time again.

  • DI container is used as service locator.
  • Object constructors explode with dependencies.
  • Everything is abstracted and injected.
  • The application tier has a reference to everything, even when it shouldn't by-design, simply because it is configuring the DI container.

I have come up with a few practices over the years to minimize the negative impact of DI and basically lock it down in an effort to prevent abuse as much as possible.

The application loader

One of the things I completely despise about DI is the fact that the application tier is forced to reference every single component just because it is responsible for configuring the container. I think this smells.

In a typical tiered design all logic runs through some kind of service or business tier. The application tier should have no knowledge of anything below that architectural level. By introducing unnecessary dependencies at this level there are more chances for accidental use of any components contained within any architecturally restricted tiers.

To prevent this from happening I started using a separate project I call "The Loader." This project is responsible for registering and configuring components on behalf of the application tier by providing a single point of access, called "The Kernel", for convention-based component registration. Here is what this looks like in a sample project.

alt text

In the image above, the DependencyModule class implements Autofac's Module to register the dependency graph. The loader project now has a reference to everything instead of the application layer, thus greatly diminishing the chance of abuse. And it just makes the application tier much cleaner.

public sealed class DependencyModule : Module
{
        protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);

            builder.Register(c => new SqlConnection(ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString))
                   .As<IDbConnection>()
                   .InstancePerHttpRequest();

            builder.RegisterType<MemcacheProvider>()
                   .As<ICacheProvider>()
                   .SingleInstance();

            ...
        }
}

The interesting bit here is the Kernel class which provides convention-based component registration for the consumer (a.k.a your app).

public sealed class Kernel
{
    private static readonly ContainerBuilder Builder;

    static Kernel()
    {
        Builder = new ContainerBuilder();
        Builder.RegisterModule(new DependencyModule());
    }    

    public static void RegisterMvcControllers(Assembly assembly)
    {
        Builder.RegisterControllers(assembly);
    }

    public static void RegisterTasks(Assembly assembly)
    {
        Builder.RegisterAssemblyTypes(assembly)
               .Where(task => typeof (IBootstrapperTask).IsAssignableFrom(task))
               .As<IBootstrapperTask>()
               .SingleInstance();
    }

    public static void RegisterMaps(Assembly assembly)
    {
        assembly.GetTypes()
                .Where(type => typeof (Profile).IsAssignableFrom(type))
                .ToList()
                .ForEach(type => Mapper.AddProfile((Profile) Activator.CreateInstance(type)));
    }

    public static void Start()
    {
        var container = Builder.Build();

        var mvcResolver = new AutofacDependencyResolver(container);

        DependencyResolver.SetResolver(mvcResolver);
    }
}

The application tier simply references the loader project and calls the Kernel to configure itself.

Kernel.RegisterMvcControllers(Assembly.GetExecutingAssembly());
Kernel.RegisterTasks(Assembly.GetExecutingAssembly());
Kernel.RegisterMaps(Assembly.GetExecutingAssembly());
Kernel.Start();

The application tier doesn't even know it's using dependency injection container at all. Therefore, there is no way to use the DI container explicitly anywhere in the application tier. This removes the anti-pattern of using container as service locator.

While this is a very simple example of the kernel, this can be extended to cover more complex configuration scenarios where an application can configure components in a variety of different ways and take a different logical path during execution.

I'm sure there are some edge cases, but so far I have successfully used this on multiple large projects with great results.

The dependency overflow

Another thing to easily do wrong when using dependency injection is to mindlessly add constructor dependencies because, well, it's so easy to do because the container will just resolve them.

The issue here is to realize that your architecture should be laid out without any reliance on any kind of inversion of control principles. Set a guideline for the number of dependencies per each component. If that number is exceeded it is time to break things up because your component is probably doing too much work. Always keep in mind the single responsibility principle.

What I found works rather well for me is to strictly adhere to the set number of dependencies in any component below the application tier while always strive to maintain this rule at the application tier (sometimes this isn't possible due to strict design specs). The thought process here is to make sure you can easily construct and test any component below the application tier. As long as this is possible, the way in which components are stitched together at the application tier isn't a very major issue.

The injection craze

DO NOT abstract and inject everything on earth. It is highly unlikely that you're going to switch database technologies, so what's the point of creating a highly flexible repository that works with ungodly amount of data access libraries? Not only are you wasting time, your abstraction is probably not going to be all-encompasing and will inevitably leak like a sieve.

Keep your design tight and sane.

Discuss »

Bootstrapping your .NET MVC apps with executable tasks

When working on large projects in ASP.NET MVC I often try to automate the development workflow as much as possible. One of such automation points is the bootstrapping logic required to fire up a typical MVC app. I'm referring to the following tasks:

  • Registering bundles.
  • Registering global filters.
  • Registering routes.
  • Registering areas.

I always find that this list easily blows up as the number of components grows. One great way to automate the registration of components at start-up is by using the Command pattern.

We'll start by creating the bootstrapper task interface.

public interface IBootstrapperTask
{
    void Run();
}

The next step is to convert all config code located in App_Start to tasks. Here is an example of the bundle registrations.

public class RegisterBundles : IBootstrapperTask
{
    public void Run()
    {
        var bundles = BundleTable.Bundles;

        bundles.Add(
            new ScriptBundle("~/assets/js/app").Include(
                "~/assets/some/kinda/js/script.js"));
    }
}

Now we just need to execute all bootstrapper tasks. This can be done using assembly scanning and reflection in Global.asax.

Assembly.GetExecutingAssembly()
        .GetTypes()
        .Where(task => typeof (IBootstrapperTask).IsAssignableFrom(task))
        .ToList()
        .ForEach(task => task.Run());

And this is all it takes! But let's not stop here. In more complicated cases your bootstrapper tasks could have dependencies in the constructor. We can solve this using dependency injection.

I will show how to handle this using Autofac. You can do a similar thing with any other dependency injection container of your choosing. Let's scan the assembly and register all IBootstrapperTask implementations with the Autofac container.

public static void RegisterTasks(Assembly assembly)
{
    Builder.RegisterAssemblyTypes(assembly)
           .Where(task => typeof (IBootstrapperTask).IsAssignableFrom(task))
           .As<IBootstrapperTask>()
           .SingleInstance();
}

You can call this from Global.asax or wherever you have your start-up code.

RegisterTasks(Assembly.GetExecutingAssembly());

Once the Autofac container is built, all tasks can execute.

container.Resolve<IEnumerable<IBootstrapperTask>>()
         .ToList()
         .ForEach(task => task.Run());

Now you can just drop new bootstrapper tasks in your App_Start (or wherever) and they will be executed automatically on start-up.

Discuss »

Fresh, new look for my blog

I've been away from my blog for a while (as you may have already noticed). I can say that it's partially due to a painfully slo-o-o-w experience running wordpress on BlueHost. I eventually decided to ditch both, build a simple blog and learn a thing or two while i'm at it. I'm well aware that most of the stuff built into this little project is a total overkill, but it was a great learning experience, so here is the full stack:

Best of all is that all of this goodness is hosted on AppHarbor for absolutely zilch! They're like Heroku for .NET trying to make .NET deployments really easy. Anyway, more posts to come.

Thanks for reading!

Discuss »

All things JavaScript – Writing better jQuery plugins

I’ve been doing quite a bit of work in JavaScript recently. It’s a major shift from regular server-side grind. I learned a few patterns and became more aware of different architectural practices when writing front-end code. I am starting to slowly get over my love/hate relationship with all things client-side. I absolutely love the responsiveness and interactivity of a modern user interface.

Yet, I despise writing JavaScript code. To me it’s the mind-boggling dynamic nature of JavaScript that makes it so complicated. So, what I’d like to do is start quick series about different JavaScript tips and tricks I learned over time, which essentially make writing JavaScript a slightly better experience (at least in my opinion).

Like many others, I write all of my JavaScript in jQuery. I’ve already talked about how to structure jQuery code, today I’d like to discuss a cool plugin pattern i picked up from Twitter Bootstrap while using it on one of my projects. Here is the skeleton.

(function () { 
    /*
     Plugin class definition
     */

    var Plugin,
        privateMethod;

    Plugin = (function () {

        /*
         Plugin constructor
         */

        function Plugin(element, options) {
            this.settings = $.extend({}, $.fn.plugin.defaults, options);
            this.$element = $(element);
            /* Do some initialization
             */
        }

        /*
         Public method
         */

        Plugin.prototype.doSomething = function () {
            /* Method body here
             */
        };

        return Plugin;

    })();

    /*
     Private method
     */

    privateMethod = function () {
        /* Method body here
         */
    };

    /*
     Plugin definition
     */

    $.fn.plugin = function (options) {
        var instance;
        instance = this.data('plugin');
        if (!instance) {
            return this.each(function () {
                return $(this).data('plugin', new Plugin(this, options));
            });
        }
        if (options === true) return instance;
        if ($.type(options) === 'string') instance[options]();
        return this;
    };

    $.fn.plugin.defaults = {
        property1: 'value',
        property2: 'value'
    };

    /*
     Apply plugin automatically to any element with data-plugin
     */

    $(function () {
        return new Plugin($('[data-plugin]'));
    }); 
}).call(this);

Calling the above plugin works like so:

$('selector').plugin();

Starting at the top we see that all of our code is inside a self-executing anonymous function. This is a pretty standard pattern in JavaScript used to isolate code into “blocks.” Next, we get to the interesting part, which sets this aside from other patterns. All of the plugin logic resides in the Plugin object. This allows you to use prototypal inheritance of JavaScript to extend plugins when necessary.

Things get a little tricky in our jQuery plugin definition. What we’re attempting to do here is store the Plugin object inside the data attribute of each element resolved through the selector. So here is what’s happening inside:

  1. If the selector in calling code resolves to single element we’ll try to pull the instance of the Plugin object from that element’s data attribute and return it.
  2. If nothing is found, assume we’re working with a collection of elements and try to iterate through it while configuring (using constructor) and storing the instance of Plugin object in the data attribute.
  3. If the calling code passes ‘true’ to the plugin, we’ll attempt to return current instance of the Plugin object. This will only work with selectors resolving to single element.
  4. If the calling code passes a string to the plugin, we’ll assume it’s the name of a method of our plugin class and attempt to execute it.

Last but not least, we’ll try to automatically apply the plugin to any element marked with its specific data attribute.

If you’re using CoffeeScript, here is the code that generates the above skeleton.

###
Plugin class definition
###
class Plugin
    ###
    Plugin constructor
    ###
    constructor: (element, options) ->
        this.settings = $.extend({}, $.fn.plugin.defaults, options)
        this.$element = $(element)
        ### Do some initialization ###

    ###
    Public method
    ###
    doSomething: () ->
        ### Method body here ###

###
Private method
###
privateMethod = () ->
    ### Method body here ###

###
Plugin definition
###
$.fn.plugin = (options) ->
    instance = this.data('plugin')

    if not instance
        return this.each ->
            $(this).data('plugin', new Plugin this, options)

    return instance if options is true

    instance[options]() if $.type(options) is 'string'

    return this

$.fn.plugin.defaults =
    property1: 'value'
    property2: 'value'

###
Apply plugin automatically to any element with data-plugin
###
$ -> new Plugin($('[data-plugin]'))

If you have questions or improvements, share them in comments. Thanks for reading!

Discuss »