Runtime Resource Authorisation in ASP.NET MVC

The Authorize attribute is a feature of the ASP.NET MVC framework that programmers learn early on. While it is a good out of the box solution for general cases, it doesn’t work well for dynamic authorisation. Take the HTTP request shown below.

GET /posts/edit/12 HTTP/1.1
Host: www.example.com

In colloquial MVC, this requests the PostsController to retrieve the contents of the post with ID 12 and display them in a form. The Authorize attribute does not determine if the currently logged in user has been granted editing rights for that specific post. At best, operations are allowed based on roles or claims, which still becomes an all or nothing situation. Either an individual user can edit all posts, or none at all.

Finer-grained control over individual resources for each user in the system requires a custom solution.

The system described below eschews the Authorize attribute entirely, and chooses to instead use filters in the ASP.NET request pipeline. It imposes the restriction that the name of the resource identifier parameter should always be well-known, such as id. Since the default route already follows this convention, this usually isn’t a problem.

Identifying the What

The first piece of the puzzle is a custom action filter called SecuredAttribute. This class inherits from System.Attribute and is applied to methods. Any controller action method that is marked with this attribute identifies as a sensitive access point that requires some kind of screening procedure before being invoked.

But this attribute only identifies the method. It does not perform any kind of screening on incoming requests. This is also why it doesn’t inherit from any of the more higher-level attributes from the MVC framework, such as ActionFilterAttribute.

public class SecuredAttribute : Attribute
{
}

The SecuredAttribute is used by applying it to the top of the controller method that needs runtime screening.

public class AdminController : Controller
{
    [Secured]
    public IActionResult Edit(int id)
    {
        …
    }
}

Implementing the How

The screening is performed by a class that implements IActionFilter. There can be multiple screening filters, and they are queued up in the GlobalFilterCollection during Application_Start(). The screening process is performed before the action method is executed, by implementing it in the OnActionExecuting method of the filter class.

public class AuthorizationFilter : IActionFilter
{
    … 
    public void OnActionExecuting(ActionExecutingContext context)
    {
        var secured = context.ActionDescriptor.GetCustomAttribute(typeof(SecuredAttribute), false).FirstOrDefault();
        if (null == secured)
        {
            return;
        }

        var user = context.HttpContext.User;
        var param = context.ActionParameters.Where(p => p.Key == "id").FirstOrDefault();
        var id = Convert.ToInt32(param.Value);

        // Invoke a service to check if the request should be allowed
        var isAllowed = securityService.IsAllowed(user, id);
        if (!isAllowed)
        {
             context.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
        }
    }
}

The filter looks for the [Secured] attribute. If the method being invoked doesn’t have the attribute, the filter immediately returns and lets the method execution proceed. If the attribute is found, the filter performs a screening procedure to determine if the request should be allowed or not. It may use a injected service class or even a third-party API to perform this action.

Since the attribute is only identifying the method, it remains simple. Discrete behaviours can be attached to the same action method, that can also be dependent on the request context (e.g. invocation through web vs. API) while maintaining a clean separation of concerns.

Some of these techniques are shown below.

Extending Beyond Simple Authorisation

The method attribute can be leveraged for performing other cross-functional requirements, which are tangent to authorisation. The secured method may require an audit trail.

public class AuditTrailFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var secured = filterContext.ActionDescriptor.GetCustomAttribute(typeof(SecuredAttribute), false).FirstOrDefault();
        if (null == secured)
        {
            return;
        }

        // Invoke a service to log the method access
        Logger.Info(…);
    }
}

The authorisation and audit trail filters can coexist and are fired independently. They use the same marker to identify the methods, but perform widely different tasks with different resources at their disposal. AuditTrailFilter can be programmed to log requests to secured location in one store and all other requests into another store, while AuthorizationFilter always allows requests to unsecured locations.

Another example is to return different responses to the client based on its type. When a request comes from a browser, its Accepts header is set to text/html, while an API client such as a SPA or a mobile app sets it to application/xml or application/json. The WebAuthorizationFilter class returns the access-denied error as a HTML view, which the browser displays as a user-friendly error page.

public class WebAuthorizationFilter : IActionFilter
{
    … 
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Return if a non-API request is received
        var acceptTypes = HttpContext.Current.Request.AcceptTypes;
        if (!acceptTypes.Contains("text/html"))
        {
            return;
        }

        var secured = context.ActionDescriptor.GetCustomAttribute(typeof(SecuredAttribute), false).FirstOrDefault();
        if (null == secured)
        {
            return;
        }

        var user = context.HttpContext.User;
        var param = context.ActionParameters.Where(p => p.Key == "id").FirstOrDefault();
        var id = Convert.ToInt32(param.Value);

        // Invoke a service to check if the request should be allowed
        var isAllowed = securityService.IsAllowed(user, id);
        if (!isAllowed)
        {
            context.Result = new ViewResult()
            {
                ViewName = "AccessDenied",
            }
        }
    }
}

The ApiAuthorizationFilter class, on the other hand, returns a HTTP status code 403 in the response. The API client generates an appropriate error view on the client-side.

public class ApiAuthorizationFilter : IActionFilter
{
    … 
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Return if a non-API request is received
        var acceptTypes = HttpContext.Current.Request.AcceptTypes;
        if (!acceptTypes.Contains("application/xml"))
        {
            return;
        }

        var secured = context.ActionDescriptor.GetCustomAttribute(typeof(SecuredAttribute), false).FirstOrDefault();
        if (null == secured)
        {
            return;
        }

        var user = context.HttpContext.User;
        var param = context.ActionParameters.Where(p => p.Key == "id").FirstOrDefault();
        var id = Convert.ToInt32(param.Value);

        // Invoke a service to check if the request should be allowed
        var isAllowed = securityService.IsAllowed(user, id);
        if (!isAllowed)
        {
             context.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
        }
    }
}

Objective-C Primer for C# Developers

A Different C with Classes

Objective-C is a different take at an object oriented implementation of C, and a rather elegant one at that. The language supports all the principles of the paradigm – inheritance, encapsulation and polymorphism. It is a strict superset of C, which is a fancy way of saying that all C code is already valid Objective-C code, and C code can be freely interspersed within an Objective-C program (and yes, you also have to deal with pointers). Objective-C compilers can compile code from both languages without trouble. While the language is staple among developers using OS X and iOS, it is perfectly suited for general purpose programming as well. However, thinking in Objective-C requires getting used to its unique syntax and an eclectic model of programming that infuses Smalltalk-style messaging, C-style statements and modern OO constructs such as protocols, understanding the role of the language runtime, and getting your head around slightly different terminology.

And since large Objective-C applications are typically written for Apple’s ecosystem, being able to converse in Cocoa is not half bad a thought. This primer assumes you already know terminology such as classes, objects and methods. With that in mind, we move on to introducing the Objective-C syntax for writing class-based code.

Classes and Instances

A class is split into two files – a header and an implementation. Let’s begin with a Shape class that we will flesh out and use through the rest of this document.

// Shape.h
@interface Shape

@end

This file declares the public interface of the Shape class. The language loves its ‘@’ symbols, so get used to them. You’ll be using them more often than you think (just one of the eccentricities of the language). The implementation is stored in Shape.m and is written as follows.

// Shape.m
#import "Shape.h"

@implementation Shape

@end

This is very similar to how one might structure files in C.

You need to instantiate an object in order to do anything with it. However, the language does not have traditional constructors like in C#. Instead, the base NSObject class implements two separate methods for object allocation and initialization – alloc and init.

Shape *s = [[Shape alloc] init];

Note: Separating the interface from the implementation might seem like a lot of effort, but it is one of the traits that Objective-C inherits from C. The advantages and disadvantages of this approach have been debated in many texts and discussion forums, which I encourage you to read. They are interesting in their own right and provide a valuable background to getting under the skin of the language.

This statement allocates memory for an instance of the Shape class and initializes the object. It can also be simplified into a single message.

Shape *s = [Shape new];

In both the above examples, alloc and new are class methods (also known as static methods). The init method is also implemented by the base class, but it is an instance method. Classes can override or implement their own versions of initializers.

A look into the past

The history of this two-step construction can be traced back to the days of NeXTSTEP, when the language was still in its infancy. The tight memory constraints of the hardware at that time often necessitated memory pooling. By separating allocation from initialization, programmers were able to reuse preinstantiated objects after reinitializing them. The practice continues today because it leaves programmers free to create custom initializers for their classes while gaining the benefits of a pre-written, generic and performant allocation method.

New allocation methods are seldom created because the existing methods meet almost every need. However, one or more new initializers are created for almost every class. Due to the separation of allocation and initialization stages, initializer implementations only have to deal with the variables of new instances and can completely ignore the issues surrounding allocation.The separation simplifies the process of writing initializers. – Erik M. Buck and Donald A. Yacktman, Cocoa Design Patterns

Messages

Procedural code gets information then makes decisions. Object-oriented code tells objects to do things. – Alec Sharp

Sending messages to objects imbibes the philosophy of tell, don’t ask as championed by Sharp. A message in Objective-C is identified by the enclosing brackets ([ and ]) around the message name and the receiver. Messages are sent by clients to instances or classes. Objects contain methods to handle those messages. Messages have a method type – either instance or class (denoted by the – and + symbols, respectively). Message signatures must declare a return type (or void if they return nothing), and the types of all parameters.

The syntax of a method declaration

All messages are declared in the class interface. The definitions are stored in the implementation.

// Shape.h
@interface Shape

- (void)scaleX:(double)x Y:(double)y;

- (void)rotate:(double)radians;

- (void)translateX:(double)x Y:(double)y;

@end
// Shape.m
#import "Shape.h"

@implementation Shape

- (void)scaleX(double)x Y:(double)y {
    // Scale this object
}

- (void)rotate:(double)radians {
    // Rotate this object
}

- (double)translateX:(double)x Y:(double)y {
  // Translate this object
}

@end

Finally, the object is instantiated and called upon by a client class.

#import "Shape.h"

...
Shape *rect = [[Shape alloc] init];
[rect translateX:20 Y:30];
...

Messages are invoked upon an object instance through the unique double square-bracketed syntax of the language. The first token is the name of the object, the second the name of the message being passed. Each subsequent token is separated by a colon and denotes a parameter to be passed to the message.

Dissecting Messages

Dynamic messaging is one of the primary enhancements of Objective-C over plain C. Rather than being bound statically at compile time, messages are resolved at runtime by the language runtime. The message itself is identified by a selector, which is a null-terminated string that contains the name of the method. The selector points to a C function pointer that implements the method. An Objective-C call…

[rect translateX:20 Y:30];

is compiled into…

objc_msgSend(rect, @selector(translateX:Y:), 20, 30);

While the internals of how a message is sent are not essential, some overview is useful when writing and debugging code.

In the example above, a Shape instance is initialized and its reference stored in the variable ‘rect’. It is then sent a message to move it 20 pixels on the X axis and 30 pixels on the Y axis. The message selector to effect the move is the string “translateX:Y:”. When the language runtime attempts to send the message to the object, it uses the entire string as the selector.

It is understandably easy to misinterpret the selector name to be a method name along with its named parameters. But it becomes clear once you read the objc_msgSend function call that Objective-C does not work this way.

A programmer can dispatch any message to an object. While the compiler will identify and warn of a potentially unsupported message, the program itself will compile. While this does seem error-prone, there is a method (heh heh) behind the madness.

Methods can be added or replaced on instances at runtime. The compiler cannot possibly identify which messages are going to be supported by an object when the program executes, due to which it allows sending messages which are not defined in the scope of the class interface.

When the program is executed, the runtime introspects the object to see if it can handle the message or not. If the object receives a message it cannot handle, the system will generate a runtime exception and your program will stop.

Declared Properties

Declared properties correspond to auto-implemented properties in C#. Unless explicitly overridden, the public interface to properties is automatically generated by the compiler.

// Shape.h
...
@interface Shape : NSObject
@property double width;
@property double height;
...
@end

This is the bare minimum that you need to write in order to implement properties in your class instance. The compiler automatically generates accessors and mutators for you. An accessor has the same name as the property name (width and height in this case) and the mutator is the property name capitalized and prefixed with the word ‘set’ (setWidth and setHeight).

// Shape.m
@implementation Shape
@synthesize width;
@synthesize height;
...
@end

To access the properties, clients can use the following syntax.

// Client.m
...
NSLog("width: %d, height: %d", [rect width], [rect height]);
[rect setWidth:30];
[rect setHeight: 22];
...

Properties can also be accessed through an alternative dot syntax.

// Client.m
...
rect.width = 20;
NSLog("height: %d", rect.height);
...

Property Attributes

Property declarations can be embellished in the interface with attributes in order to control how they work. There is no change required in the implementation.

// Shape.h
...
@property (readonly) double width;
...

The readonly attribute makes the property only viewable. The compiler flags any attempts to call setWidth as errors and stops the compilation process. While property attributes have many subtleties that must be thoroughly understood in order to master the feature, beginners can go with the most general guidelines.

Storage
  • Use assign for scalar properties (native numeric types, structs, enums).
  • Use retain for object types (NSString, NSNumber, etc.). Creates a new reference to the object instance and releases the old one.
  • Use copy for object types. Creates a new instance based on the properties of the old one. Releases the old instance.
  • Use strong for object types that increment reference counts. This is the recommended technique for objects at the top of a hierarchy to reference their child objects. This ensures that the child objects will not be cleared as long as the parent object exists.
  • Use the weak attribute for references to parent objects from child objects. If the parent object is destroyed, its reference in the child object is automatically cleared off and prevents memory leaks.
Mutability
  • The readonly attribute makes a property immutable. Outside classes cannot modify its value. The class itself also cannot make any changes through the property mutator (since there isn’t one), but can change the value of the underlying field directly.
  • The readwrite attribute makes a property mutable by outside classes by auto-generating the mutator and accessor methods.
Concurrency
  • Non-threadsafe code can get away with using nonatomic properties.
  • Use atomic for properties that must work in a multithreaded environment.
API
  • The getter attribute explicitly declares the name of the accessor method. Use this to override the default name of the accessor.
  • The setter attribute works similarly to declare the name of the mutator method.

Instance Variables

A field in C# corresponds to instance variables (or ivars) in Objective-C. An instance variable exists throughout the lifetime of the object and is accessible within the scope of the objects methods – public and private. Outside classes cannot access an ivar directly.

// Shape.h
@interface Shape : NSObject {
  int _width;
  int _height;
}
...
@end

The compiler can automatically synthesize ivars for properties. The auto-generated variable has the same name as the property, prefixed by an underscore (_). This can be overridden in the implementation file using the @synthesize statement to link them to explicitly declared variables.

// Shape.m
#import "Shape.h"

@implementation Shape @synthesize width = myWidth; ... @end

Protocols

Protocols correspond to interfaces in C#. They are header files which declare a list of method signatures. Developers can declare that a class implements those methods in the header file. The compiler checks this and flags any classes that do not implement those methods.

Classes that implement all methods declared in a protocol fully are said to conform to it.

// FilledShape.h
@protocol FilledShape

- (void)setFill(Fill *)fill;

- (void)clearFill;

@end

The Shape class can declare that it conforms to the FilledShape protocol by following its class name with the name of the protocol.

// Shape.h
#import "FilledShape.h"

@interface Shape : NSObject <FilledShape> ... @end

Classes can implement as many protocols as required. Each protocol name should be separated by a comma within the two angled brackets (<>).

// Shape.h
#import "FilledShape.h"
#import "OutlinedShape.h"

@interface Shape : NSObject <FilledShape, OutlinedShape>
...
@end

Objective-C protocols offer the option of declaring required and optional methods. This makes it possible to write classes that implement only some, but not all methods of a certain interface. While this again does seem like a code smell to many programmers, it does come in handy given the dynamic nature of Objective-C.

All methods declared in a protocol are public. Protocols cannot define private methods.

In Closing

Like many other languages, the syntax and many features of Objective-C are fairly easy to grasp. Apple’s excellent implementation of the Foundation Framework, UIKit and Cocoa frameworks make it easy even for novices to write significant applications without much effort. But like everything else, true mastery comes only with practice and an understanding of the underlying runtime that powers the language.

Additionally, while OOP is great for increasing productivity, developers must also take time out to grasp the C underpinnings that form the foundation of Objective-C. This knowledge not only makes for a well-rounded education of the language, but also opens up the ability to harness the raw power of C when necessary, which is an important benefit of Objective-C.

Storing Values with Bit Packing and Unpacking

Bit packing and unpacking is a handy way of consolidating multiple data values into a single variable, thus compressing the amount of data being stored or transmitted. The number of values that can be stored depends upon the width of the data to be stored as well as the type of the value that it is packed into. A simple byte can store up to 8 bits of data. Larger types such as ints can store up to 16, 32 or 64 bits. This is an especially efficient technique for storing several small-width values, often smaller than the smallest width supported by a platform (such as byte or boolean flags) into a single large value such as a 32-bit integer.

Bit flags are commonly used for implementing low-level features, such as storing file access-permissions or packing values into a single value before transmitting across a bus. However, they can be applied with equal ease to higher level tasks such as storing user preferences or choosing which widgets to display from an enumerated list. We will see here how to use bit flags to store font formatting preferences, and apply them later to a label.

Bitwise Operators

There are a couple of operators we need to understand before we can move on to the implementation. Bitwise operators, by definition, work on individual bits inside a value. Since they are implemented directly by the processor itself, they are much faster than arithmetic operators such as division and multiplication. We will use bitwise AND (&), bitwise OR (|) and left shifts (<<) in this exercise.

A bitwise AND operation takes the binary representations of two values and performs a logical AND operation on each bit. The result is 1 in every position where both the bits are 1, and 0 if either or both bits are 0.

    001010
AND 011011
    ------
    001010

Bitwise OR on the other hand, compares two bits in corresponding positions, and sets the result to 1 if either of them is 1, or to 0 if both of them are 0.

    001010
OR  011011
    ------
    011011

Bitwise left shift operator moves individual bits within a single value by the number of places specified in the second operand. The value is padded with 0s on the right, and the left-most bits are dropped off.

    001010 << 1 = 010100

Implementation

We set up a simple Windows Forms project and draw three checkboxes and one label on the form. The aim is to have the checkboxes control three font properties of the label – weight, style and underlining. All checkboxes are given appropriate labels and configured to execute the _changeFormatting method of the form every time the CheckStateChanged event is fired. The code for this method is shown below.

private void ChangeFormatting(object sender, EventArgs e)
{
    byte flags = 0;

    flags = (byte)(
        Convert.ToByte(this.chkUnderline.Checked) << 2 |
        Convert.ToByte(this.chkItalic.Checked) << 1 |
        Convert.ToByte(this.chkBold.Checked)
        );

    Font f = new Font(this.label1.Font.FontFamily, this.label1.Font.Size, (FontStyle)(
        (flags & (byte)FontStyle.Underline) |
        (flags & (byte)FontStyle.Italic) |
        (flags & (byte)FontStyle.Bold)
        ));

    this.label1.Font = f;
}

Packing

In the first statement, the flags variable is populated with the values of each checkbox. We want to store the three flags in the last three bits of a single byte.

PositionSetting
7Unused
6Unused
5Unused
4Unused
3Unused
2Underline
1Italic
0Bold

In order to do so, we take the value of each boolean (either true or false), convert it into a byte, then shift it by an appropriate number of positions. The value of the underline flag is to be stored in the 2nd bit (starting from 0). So we left-shift its value by 2. Similarly, the italic flag is stored in the 1st position, so its boolean value is shifted by 1. The value of the bold flag does not need to be shifted at all.

    00000001 << 2 = 00000100 // Underline
    00000001 << 1 = 00000010 // Italic
    00000001                 // Bold (no shifting required)

A consolidated value can be generated by ORing the three values together.

    00000100
 OR 00000010
 OR 00000001
    --------
    00000111 // Decimal value 7
    00000000
 OR 00000010
 OR 00000001
    --------
    00000011 // Decimal value 3
    00000100
 OR 00000000
 OR 00000001
    --------
    00000101 // Decimal value 5

The decimal value can then be stored in a database or other persistent storage system as an integer or byte. This is better than having to store three boolean fields. This information can transmitted across systems too as a packed unit, to be unpacked later only when the preferences have to be applied to a display element.

In our example, we are unpacking and applying the values immediately for brevity. But a more practical situation would probably involve serializing the value somewhere, then deserializing and applying the font properties later at another location.

Unpacking

In order to apply the font styles on a display element, the individual values of each style parameter must be extracted from the packed value and then applied. The .NET framework defines enumerations for each of these style parameters in the System.Drawing.FontStyle enum. The values for each style parameter are listed below.

SettingDecimal ValueBinary Value
Regular000000000
Bold100000001
Italic200000010
Underline400000100

You will notice that each enumeration is double the value of its predecessor, hence moving the digit 1 by one position leftwards with every increase. This is a key feature of bit flags. Each element differs from the others only in the position of the 1 bit. Thus, the value of a given flag can be extracted from the packed value by ANDing the packed value with the value of the enumeration.

     00000111 // Packed value decimal 7
AND  00000100 // Underline enum decimal 4
     --------
     00000100 // Result - show underlines

This operations shows that the value of the underline flag is true. If the packed value was the decimal 3 instead of 7, then the operation would play out as shown below, resulting in the value 0 for the underline flag.

     00000011 // Packed value
AND  00000100 // Underline enum
     --------
     00000010 // Result - hide underlines

All that is needed then is to convert the result byte into a boolean and apply it wherever required. In our example above, the constructor of the Font class requires the values packed together any way as a FontStyle enum. To do this, each bit is ANDed with its corresponding enum, then all of them are combined together again using an OR operation. The resultant byte is cast into a FontStyle before being passed to the constructor.