1

On an Azure Mobile App Services server side app using MVC 5, Web API 2.0, and EF Core 1.0, controllers can be decorated like so to implement token based authentication:

// Server-side EF Core 1.0 / Web API 2 REST API
[Authorize]
public class TodoItemController : TableController<TodoItem>
{
  protected override void Initialize(HttpControllerContext controllerContext)
  {
     base.Initialize(controllerContext);

     DomainManager = new EntityDomainManager<TodoItem>(context, Request);
  }

  // GET tables/TodoItem
  public IQueryable<TodoItem> GetAllTodoItems()
  {
     return Query();
  }
  ...
}

I want to be able to do something similar on the client side where I decorate a method with something like [Authorize] from above, perhaps with a, [Secured], decoration, below:

public class TodoItem
{
    string id;
    string name;
    bool done;

    [JsonProperty(PropertyName = "id")]
    public string Id
    {
        get { return id; }
        set { id = value;}
    }

    [JsonProperty(PropertyName = "text")]
    public string Name
    {
        get { return name; }
        set { name = value;}
    }

    [JsonProperty(PropertyName = "complete")]
    public bool Done
    {
        get { return done; }
        set { done = value;}
    }

    [Version]
    public string Version { get; set; }
}

// Client side code calling GetAllTodoItems from above
[Secured]
public async Task<ObservableCollection<TodoItem>> GetTodoItemsAsync()
{
    try
    {
        IEnumerable<TodoItem> items = await todoTable
            .Where(todoItem => !todoItem.Done)
            .ToEnumerableAsync();

        return new ObservableCollection<TodoItem>(items);
    }
    catch (MobileServiceInvalidOperationException msioe)
    {
        Debug.WriteLine(@"Invalid sync operation: {0}", msioe. 
    }
    catch (Exception e)
    {
        Debug.WriteLine(@"Sync error: {0}", e.Message);
    }

    return null;
}

Where [Secured] might be defined something like this:

public class SecuredFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Check if user is logged in, if not, redirect to the login page.
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        // Check some globally accessible member to see if user is logged out.
    }
}

Unfortunately, the above code only works in Controllers in MVC 1.0 applications and above according to the Microsoft article on "Creating Custom Action Filters": https://msdn.microsoft.com/en-us/library/dd381609(v=vs.100).aspx

How do I implement something like a "Custom Action Filter" that allows me to use the "[Secured]" decoration in a Mobile App Service client instead of the server? The answer will help me create custom authentication from the client side and keep the code in one location without complicating the implementation, i.e., it is a cross-cutting concern like performance metrics, custom execution plans for repeated attempts, logging, etc.

Complicating the scenario, the client also implements Xamarin.Forms for iOS and has to be a functional Ahead of Time pattern due to iOS's requirement for native code, JIT is not yet possible.

Aaron
  • 583
  • 1
  • 5
  • 12
  • Have you thought about extending the custom authorize with your own needs??? – COLD TOLD Mar 29 '16 at 21:52
  • I don't know how to do that. What do you mean by "extending the custom authorize?" This is client side, so I'm assuming you mean LoginAsync. – Aaron Apr 01 '16 at 02:10

2 Answers2

1

What you are more generally describing in known by a few different names/terms. The first that comes to mind is "Aspect Oriented Programming" (or AOP for short). It deals with what are known as cross cutting concerns. Im willing to bet you want to do one of two things

  1. Log exceptions/messages in a standardized meaningful way
  2. Record times/performance of areas of your system

And in the generala sense, yes C# is able to do such things. There will be countless online tutorials on how to do so, it is much too broad to answer in this way.

However, the authors of asp.net MVC have very much thought of these things and supply you with many attributes just as you describe, which can be extended as you please, and provide easy access to the pipeline to provide the developer with all the information they need (such as the current route, any parameters, any exception, any authorization/authentication request etc etc)

This would be a good place to start: http://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/

This also looks good: http://www.dotnetcurry.com/aspnet-mvc/976/aspnet-mvc-custom-action-filter

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Those are great ideas and I may use this for log and performance metrics. Currently, my purpose is for client side custom authentication (try/catch with check for HTTP unauthorized, then displaying login modal if necessary). Unfortunately, it seems the AOP stuff for authorization in Azure Mobile App Services is intended for MVC 5+ on the server side, and only built into LoginAsync (not custom auth) on the client side. I'm trying to build this wrapper on the client side where MVC 5+ isn't used, so I don't have the 'unknown' and moving target dependency on LoginAsync. – Aaron Mar 29 '16 at 22:13
1

The reason attributes work in the scenarios you describe is because other code is responsible for actually invoking the methods or reading the properties, and this other code will look for the attributes and modify behaviour accordingly. When you are just running C# code, you don't normally get that; there isn't a native way to, say, execute the code in an attribute before a method is executed.

From what you are describing, it sounds like you are after Aspect Oriented Programming. See What is the best implementation for AOP in .Net? for a list of frameworks.

In essence, using an appropriate AOP framework, you can add attributes or other markers and have code executed or inserted at compile time. There are many approaches to it, hence why I am not being very specific, sorry. You do need to understand that the AOP approach is different from how things like ASP.Net MVC works as AOP will typically modify your runtime code (in my understanding anyway and I'm sure there are variations on that as well).

As to whether AOP is really the way to go will depend on your requirements, but I would proceed with caution - it's not for the faint of heart.

One completely alternative solution to this problem is to look at something like Mediatr or similar to break your logic into a set of commands, which you can call via a message bus. The reason that helps is that you can decorate your message bus (or pipeline) with various types of logic, including authorization logic. That solution is very different from what you are asking for - but may be preferable anyway.

Or just add a single-line authorisation call as the first line inside each method instead of doing it as an attribute...

Community
  • 1
  • 1
flytzen
  • 7,348
  • 5
  • 38
  • 54
  • I was hoping to wrap the client methods in a _somewhat_ universal try / catch that will catch a MobileServiceInvalidOperationException, then retry the execution in a custom execution plan (i.e., 3 tries hitting Azure before an error is displayed in the UI). The solution uses Xamarin.Forms for cross-platform compatibility, so I'm also limited there. I will look into your suggestions, thank you. – Aaron Mar 29 '16 at 22:25
  • 1
    One approach I've taken to that problem is a static method which takes a lambda and then tries to execute that lambda, retrying and catching exceptions etc. You still have to actually use that method, but it beats repeating it. But, mediatr may actually be a good choice as you could handle that with a decorator on the pipeline. – flytzen Mar 29 '16 at 22:32
  • It look likes PostSharp supports Xamarin (and IOS), here is a link to someone looking for exactly what I'm trying to do: https://forums.xamarin.com/discussion/34976/postsharp-support-for-xamarin – Aaron Apr 01 '16 at 02:14
  • Unfortunatelly PostSharp is a commercial product – pixel Nov 10 '17 at 18:37