Question

Does anyone have an example of modelling access control in MongoDB? The situation I'm thinking of is:

There are a set of resources, each being their own document (e.g. cars, people, trees etc.).

A user can gain access to a resource through an explicit grant, or implicitly by being the owner of a resource, existing in another collection (e.g. a role) or some other implicit ways.

In one collection.find() method, that could have skip and limit options applied (for pagination), is there a way to check all these explicit and implicit paths and produce a result of resources a user has access to?

In MySQL we have modelled this using a grants table with resource id, granting user id, authorized user id and operation (read, write etc.). We then, in one query, select all resources where at least one subquery is true, and the subqueries then check all the different paths to access e.g. one checks for a grant, one checks for ownership etc.

I just can't wrap my head around doing this in MongoDB, I'm not sure if it's even possible...

Thanks

Was it helpful?

Solution

You can't query more than one document at a time. Ideally, shouldn't access control be a part of the business logic. Your backend php/c#/language ought to ensure that the current request is authorized. If so, then simply query the requested document.

If you feel, you need to implement the exact same structure in mongodb, which I suggest you don't, then you will need to embed all those fields (the ones from the other mysql tables that help you identify whether the request is authorized) in each and every document of every collection. You will be duplicating data (denormalizing it). Which brings the headache of ensuring that all the copies are updated and have the same value.

Edit 1:

Lets talk about Car document. To track its owner, you will have owner property (this will contain the _id of the owner document). To track all users who can 'use' (explicit grant) the car, you will have an array allowerdDrivers (this will contain the _id of each user document). Lets assume the current user making the request belong to the 'admin' role. The user document will have an array applicableRoles that store the _id of each role document applicable.

To retrieve all cars that the user has access to, you only need to make two queries. One to fetch his roles. If he is an admin, return ALL cars. If he is not, then make another query where owner equals his id or allowedDrivers contains his id.

I understand your actual use case may be more complicated, but chances are there is a document-oriented way of solving that. You have to realize that the way data is modelled in documents is vastly different from how you would model it in a RDbMS.

OTHER TIPS

Doing it in business logic would be painfully slow and inefficient.

How so? This is business logic, if user a owns post b then let them do the action (MVC style), otherwise don't.

That sounds like business logic to me and most frameworks consider this business logic to be placed within the controller action (of the MVC paradigm); i.e. in PHP Yii:

Yii::app()->roles->hasAccess('some_view_action_for_a_post', $post)

I think that by doing it in the database end you have confused your storage layer with your business layer.

Also with how complex some role based permission actions can get the queries you commit must be pretty big with many sub selects. Considering how MySQL creates and handles result sets (sub selects ARE NOT JOINS) I have a feeling these queries do not scale particularly well.

Also you have to consider when you want to change the roles, or a function that defines a role, that can access a certain object you will have to change your SQL queries directly instead of just adding the role to a roles table and assigning the object properties for that role and assigning users that role (AKA code changes).

So I would seriously look into how other frameworks in other languages (and your own) do their RBAC because I think you have blurred the line and made your life quite hard with what you have done, in fact here might be a good place to start: Group/rule-based authorization approach in node.js and express.js

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top