Page 1 of 1

User Role Security with autogenerated model queries

Posted: Thu Jun 30, 2011 12:19 am
by Benjamin
My question is this: In a multi-role environment how to best prevent users from arbitrarily updating database fields they do not have permission to change with the following setup:

I've written a base model class I can extend in order to save time writing redundant code and database queries.

Code: Select all

class user extends baseModel {
    public function update($id, $data) {
        try {
            $data = $this->_filterIn($data);
            $this->_validateCommon($data);
            $this->_validateUpdate($id, $data);

            return parent::update($id, $data);
        } catch (Exception $e) {
            $this->_setError($e->getMessage());
        }
    }
}
The base model reads the database schema and takes care of writing all of the database queries depending on what fields are passed fully automatically. It matches the array keys to the table field names and recognizes default field values, primary keys and other things.

Now at the controller layer it would look something like this:

Code: Select all

class userController extends controllerBase {
    public function updateAction() {
        if (is_post()) {
             $user = new user();

             if ($user->update($id, $_POST)) {
                 // do something
             } else {
                 // do something
             }
        }
        include SOME_CONSTANT . 'pages/user/update.php';
    }
}
This works great in the sense that forms, controllers and models can all be created very quickly.

Re: User Role Security with autogenerated model queries

Posted: Thu Jun 30, 2011 10:23 am
by alex.barylski
I'm not sure I understood the question, and if I did, the answer is going to vary wildly from developer to developer. Personally that is to fine-grained access control for me -- it makes management of permissions so tedious.

I use a controller:action level access control implemented as a simple front controller plugin and simply map groups to given actions so I just need to maintain a basic INI file (or similar).

If I need fine-grained control I usually take that as a sign that the interface is not designed as elegantly as it could be. For instance there is some admin functionality in a end-user control panel. In which case controller:action level access control is not sufficient and I would need to add a conditional check in the model to permit updating a given field ONLY if they have admin privileges.

So the question becomes, do I remove that single field from view and re-factor the model to accommodate the edge case or do I remove it completely and throw that field into it's own controller:action with a view specifically for that?

While it seems like more work, that is typically the solution I opt for as I find it keeps the code more aligned with SRP and it's easier to maintain, IMO.

Cheers,
Alex

Re: User Role Security with autogenerated model queries

Posted: Thu Jun 30, 2011 12:07 pm
by Benjamin
Essentially the model doesn't care what fields are sent to it. If you send it a field, the field will be updated.

The controller is just taking the entire $_POST variable and passing it to the model.

This is fine, except when you want to control what fields should/should not be updated. I'm trying to find an elegant solution, otherwise I will just need to manually passs the fields to the models depending on the permissions of the user.

Re: User Role Security with autogenerated model queries

Posted: Thu Jun 30, 2011 1:39 pm
by Christopher
Seems like you should be able to specify in both the Controller and Model what fields are allowed. There are many ways to do that, the question is where do you want the information about what fields are available for each role? Seems like the Model is the place for that.

Re: User Role Security with autogenerated model queries

Posted: Thu Jun 30, 2011 2:37 pm
by Benjamin
Here's what I don't want to do:

Create different methods for different roles in the models, because it doesn't feel right.
Create a system where an admin can specify exactly what fields in each table each role can modify, because that seems like it would be a real headache to manage.

I suppose the best way to do this is create different controllers for different roles and whitelist the fields they are able to send. This adds extra files and extra code to each controller though.

Re: User Role Security with autogenerated model queries

Posted: Thu Jun 30, 2011 7:06 pm
by Christopher
Benjamin wrote:Create different methods for different roles in the models, because it doesn't feel right.
Agreed, does not sound good.
Benjamin wrote:Create a system where an admin can specify exactly what fields in each table each role can modify, because that seems like it would be a real headache to manage.
It seems like the best solution must be able to "specify exactly what fields in each table each role can modify". The question becomes -- where to store that data. The options: in the Model code itself, set in the Model by the Controller, in a data source accessible by the Model.
Benjamin wrote:I suppose the best way to do this is create different controllers for different roles and whitelist the fields they are able to send. This adds extra files and extra code to each controller though.
I don't think different Controllers for different roles sounds right, but maybe I am not understanding your plan. It seems like the Access Control subsystem should be a service that the Controllers use to decide on program flow.

Re: User Role Security with autogenerated model queries

Posted: Thu Jun 30, 2011 11:39 pm
by Benjamin
Yeah it really already has an access control subsystem. This is just a vulnerability caused by simplicity. Based on the notion that the easiest solution is generally the correct solution, I think the way to go is to avoid sending the $_POST variable itself to the models and instead only pass the relevant field names.

Re: User Role Security with autogenerated model queries

Posted: Fri Jul 01, 2011 4:15 am
by matthijs
I recently had a similar kind of issue. I solved it by passing only the relevant fields. So say role "admin" can access AdminController, in which a method updateUser updates all user fields.
Then role "partner" can not access AdminController, but can access PartnerController, in which a method updateUser updates only a limited amount of user fields.

I thought this was the most logical way to do, since individual methods don't always insert/update the exact same fields. Sometimes you just want to update an email address, other times only a password, etc

Re: User Role Security with autogenerated model queries

Posted: Thu Jul 07, 2011 5:39 pm
by VladSun
Benjamin wrote:Create a system where an admin can specify exactly what fields in each table each role can modify, because that seems like it would be a real headache to manage.
http://dev.mysql.com/doc/refman/5.1/en/grant.html

If they do it why wouldn't you? Not such a big headache - I've used such fine grained ACL. I posted here a code that could be used for "ORM-based ACL" - viewtopic.php?f=50&t=89528 . The "source" topic is also interesting viewtopic.php?f=19&t=89300

The big problem is about determining ownership, IMHO.