4
votes

I have already made the database and the php code needed to implement this customized ACL system. Now I have to 'Authorize' the current user, and that's where I need your advices.

The system is based on a flexible permission assignment both to the system users and system modules. It has also some predefined, let say user-groups, with the ability to make entirely customized groups also. A global rule could also apply on top of the ACL, but it has the lowest priority over groups or users assigned permissions.

To picture it better:

Predefined Groups:

  1. Limited (No Access)
  2. Basic User
  3. Power User
  4. Administrator
  5. Visitors (Sample of a customized group)

Here are the access levels (name / value pairs):

  • disallow / 0
  • allow / 1
  • deny / 2
  • allow if owner / 3

Note: 'Allow' has the higher priority on 'Disallow', so if you have user X 'Disallowed' on Group A, but 'Allowed' on Group B on a certain access, so he would 'Allowed' finally. On the other hand, if user X has the 'Full Access' by being a member of 'Administrator' Group, but if he just 'Denied' on a certain access, he has not the access at the end, that means 'Deny' has higher priority on 'Allow'.

At the top-level you may have something like these:

  • "Administrator" * "1", which means Administrators have full access on the system
  • "Visitors" * "0", which means Visitors are not allowed on anything

My question is how to process these kind of checks? Imagine we have a simple authorization mechanism. We would have some indexes in our $_SESSION['user'] like $_SESSION['user']['login'] = true; and $_SESSION['user']['id'] = $row['user_id'], right?

Now, if you wanted to implement this mechanism on your script, how you're gonna do it?

I might check for the global access rules at first. Then I would look if the user has already logged-in or not. If yes, just getting all of his groups, and then looking on the permissions' table to see which permissions are assigned to his groups and his user id, and then storing them on the user session. Then when the module says this is my needed permissions to run, I would look then to see if the user has sufficient access to the requested module or not.

Looks pretty complex! Any helps or advice are highly appreciated! :)

Edit:

I'm not using any frameworks. Actually I use, but it's my own. So, there is no pre-made ACL here!

Update:

Do you have any idea about an efficient way to prioritize (overwrite/replace?) ACLs?

Deny is highest, then Allow and then Disallow. Also User assigned ACLs are highest, then Group ACLs and finally Global ACLs.

Here is what I came up with that finally:

There is an Array, like this:

$_SESSION['ACL'][$module][$action] = $access_level; // 0, 1, 2, 3

First, I would looking for all the Global Rules *, and will put them on the array:

// The current user can see the map, applied by a global rule
$_SESSION['ACL']['map']['render'] = 1;

// All the other permissions are disallowed by default
$_SESSION['ACL']['*']['*'] = 0;

// He can edit his preferences, (Owner)
$_SESSION['ACL']['user']['*'] = 3;  

Then, I will look for Group based ACLs:

// User could access the Analyze module, all the methods 
// with Permission Name "report". Applied by being a member 
// of "Moderator" Group
$_SESSION['ACL']['analyze']['report'] = 1;

// User NOT allowed to access "groups" module, let say
// it reserved for "admin" group! - To see the ACLs' Overwriting!
$_SESSION['ACL']['groups']['*'] = 0;

After all, I would looking for User assigned ACLs:

// User have Full Access to the "groups" module.
// It's gonna replace the last ACL, applied by "Moderator" group
// Note that the order of processing ACLs is IMPORTANT!
$_SESSION['ACL']['groups']['*'] = 1;

I guess it would works perfectly, any ideas?

It Works Pretty Well Now :)

2
Are you doing this in an MVC environment?Pitchinnate
No, I hate overhead! I have my own framework. I knew that frameworks usually have their own ACL! :)Mahdi
Is your custom framework structured as an MVC? I don't care if it is custom or not. The solution I have only applies if your framework is structured as an MVC.Pitchinnate
No, it's not strictly MVC, however it has some similarities. You may share your thoughts! I'm sure that would helps! :)Mahdi
For you priorities just do your searches through the $_SESSION['ACL'] array in the correct order.Pitchinnate

2 Answers

2
votes

Here is the way I handle it in an MVC environment, create a table with this structure:

(id, group_id(int), user_id(int), controller(varchar), action(varchar)) 

Then I use -1 on group and user_id to represent a wildcard, and a * on the controller and action. So in your example an administrator can do anything (1,4,-1,,). Or lets say Power Users can modify users (2,3,-1,user,*). Or if you want to give a single person (user_id of 34) a permission regardless of what group they are in (3,-1,34,user,update). If you wanted to store your 0-3 for allow, disallow, just add a column. Then you just check which controller and action is being called and find any permissions that apply to the person's group(s) and to them specifically.

1
votes

Just create your permissions/ groups table:

id, group/permission name

Then, create your many to many table linking groups to users:

id, user_id, group_id

You don't need access levels if you're just using group permissions.

Then, in your code, just check the user for the group like this:

function checkAccess($pageLevelRequired)
{
  // run query based on current user session id
  // run your query to check if the current user belongs to the group required to view this page.
}

Make sense?