8
votes

We have a Web Api 2 OData v3 service which we need to implement fairly complex authorization on. We are using Breeze within our client code and when an OData v4 version of Breeze is released we are upgrading our API to OData v4 so the solution needs to be able to work on both OData versions.

This diagram gives a very basic view of the sort of entity model we are working with (Sorry, not enough reputation points for an image):

 ServiceCompany
     |   
     |  
    /|\  
Manufacturer
     |   
     |  
    /|\    
    Site
     |   
     |  
    /|\  
  SiteArea  -------
     |            |
     |            |            
    /|\          /|\ 
 Equipment     Instrument
                  |
                  |
                 /|\
               Channel

A SiteArea has a property of “OperatingFunction” – this shows what stage of the manufacturing process occurs at this site area location.

A user could be

  • a person sitting at Manufacturer level and has access all of their Site data
  • a person sitting at Manufacturer level and has access to some, but not all of their SiteAreas, and therefore only a subsection of their SiteArea data
  • a person sitting at ServiceCompany level who has access to some Manufacturers, and within that only some Sites within those Manufacturers, and maybe only certain OperatingFunctions of a SiteArea.

A request will come in for Channel data and we need to be sure to only return or update (depending on the request type) the data that the individual is allowed to affect.

Upon initial investigation the obvious choice for implementing this appeared to be QueryInterceptors and ChangeInterceptors, meaning we could add further filter preferences based upon the claims being sent in with the request. However it appears that Query/ChangeInterceptors are part of Wcf, not WebApi, and on top of that they are only part of the v1-3 Wcf OData implementation, there is nothing so far for OData v4.

We could, of course, write the filter code into each method, but that really seems like it would be a nasty way to implement something that is essentially a cross cutting concern.

We have looked at the EF6 interceptors but have arrived at the conclusion that they’re too far down the stack, ideally we don’t want to be dealing with the SQL command code itself.

We have briefly considered whether we should use a role/task based authorisation pattern and have come to a solid conclusion that that would not work for us as it would be too constricting for future developments and wouldn’t work in our scaling plans.

Essentially we have come to the conclusion that we need to implement our own QueryInterceptorAttribute but thought it worth asking if we have missed something before trying to reinvent the wheel.

Thanks.

Edit : I forgot to mention that another option may be to look at using the Decorator pattern, we're using Unity and with that could add the functionality we require : Unity Interception

1
Yes a custom QueryInterceptorAttribute is way to proceed forward in this case, that would help in handling all scenarios in a seamless mannerMrinal Kamboj

1 Answers

0
votes

I went down the QueryInterceptor path and it's nothing but a bottomless abyss of abstraction. I could not find a hook at any point where things were a) decipherable and/or b) not read-only.

Have a look at this article by Dominick Baier of Thinktecture.
http://leastprivilege.com/2014/06/24/resourceaction-based-authorization-for-owin-and-mvc-and-web-api/

I am using this claims-based resource/action authorization model to great effect. I also suggest viewing Dominick's tutorials on Pluralsight. They helped me a great deal.