Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent users to access other user's data with dotnet core and RESTful APIs?

I'm trying to find the best solution to a simple problem that is not largely discussed around.

My application have lots of users that can create and edit data. An user should only see and edit his data, not other's.

Think about Alice, who has a Restaurant A with a Menu MenuA, and Bob, who has a Restaurant B and a Menu MenuB.

I have APIs to CRUD restaurants and menus and I can easily only authorize logged users with correct claims and roles. What I want to do now is prevent Bob to access Alice's restaurant or menu, and viceversa. For instance, Bob should be authorize to PUT /api/restaurants/B but should be unauthorized to PUT /api/restaurants/A or even PUT /api/restaurants/A/menus/x

A possible solution is the one provided here ASP.NET MVC Attribute to only let user edit his/her own content. This solution requires to create a custom Authorize attribute to actively check if the logged user is the proprietary of the accessed entity. The entities have an userId field to check if the user making the request is the owner of the data. This solution is nice and clean but lacks some features. Every entity in the model should have an userId field and can only be accessed by the owner OR for each entity I need to navigate to the root entity of the authorization model (ex. accessing Menu i need to query for the parent entity Restaurant to check if MenuB is inside a Restaurant owned by the user). To achieve multiple owners (ex. the restaurant managers) the logic will be a lot more complex. I am also worried about the overhead here, since basically every call requires to do some queries to check data access, but it will probably not be an issue.

Is there a best practice?

like image 293
JoP Avatar asked Mar 07 '17 17:03

JoP


1 Answers

What you want do is implement attribute-based access control or abac.

In the ABAC architecture, you have the notion of a policy enforcement point (PEP) which intercepts the API call and determines whether the call should go through. The PEP converts the API call into an authorization request and sends it off to a central Policy Decision Point (PDP).

The following architecture summarizes the flow.

ABAC Architecture Applied to .Net API

The PDP is configured with a set of policies that determine what is allowed and what is denied. For instance you can write policies such as:

  • The owner of a restaurant can view the restaurant page
  • The owner of a restaurant can edit that restaurant's menu.
  • A customer can view any restaurant's menu if it is public.

There are two languages you can write policies in: xacml or alfa.

For instance, in ALFA, a policy would look like:

namespace restaurant{
    attribute userId{
        category = subjectCat
        id = "restaurant.userId"
        type = string
    }
    attribute owner{
        category = resourceCat
        id = "restaurant.resourceCat"
        type = string
    }
    policy restaurant{
        target clause objectType == "restaurant"
        apply firstApplicable
        rule ownerCanView{
            target clause actionId == "view"
            permit
            condition userId == restaurant.owner
        }
    }
}

All you need is to use a XACML 3.0 Policy Decision Point. There are Java and .NET implementations as well as commercial ones. Have a look at this blog post on .Net authorization.

like image 58
David Brossard Avatar answered Nov 07 '22 04:11

David Brossard