Real World Access Control

By Rob Conner aka "rtconner"
Cake AC is a very powerful but generic access control sytem. Lets face it, the only real use for Access Control is User permissions. So let us look at the common every day use for Access Control.
I'm going to assume we all looked at (and were confused by) the Cake Manual Tutorial on Access Control. I'll also assume you all want to know how you might practically use Cake AC to implement User and Group permissions.

Cake Acces control was not made specifically for User/Group permissions control. It is simply a generic access control system to be used for anything. It can be used for User/Group permissions, but we have a bit of work to do to figure out exactly how.

Understanding the concepts

How can Cake AC be used for User and Group permissions? Lets simplify things, by talking in terminology that we all understand...

ARO (Access Request Objects) = Users or Groups
  1. link_id = User ID (or 0 if it is a Group)
  2. parent_id = Id of Group that a User Belongs to
  3. alias = Unique Id/Name of Users and Groups

ACO (Access Control Objects) = Your Controllers or Actions
  1. link_id = A Unique Page Id (I have no idea what that is)
  2. parent_id = Id of Controller that an Action belongs to
  3. alias = Unique Id/Name of Controlers or Actions

ACL (Access Control List) = List that holds User/Group data access restrictions to Controllers and Actions
  1. aro = Your user or group
  2. aco = your controllers or actions
  3. action = You define the actions, generally read, write, etc..

So some things of concern here, now that we have this in english.

While Cake AC does not force aliases of anything to be Unique.. well as you might expect, you do run into problems if they are not unique. What will happen if you have a User named 'Smith' and you are putting him into a group called 'Smith'? Well, unless you add something, the system will wonder why you are trying to make 'Smith' a parent of himself.

So with that all said, I set my system up so that references to Users were always made with the users Unique Id (ARO link_id) and references to Groups were made with the Group name (ARO alias)
Download code // set user with id 2 to be part of the group 'admins'
$aro->setParent('Admins', 2); 
// just made sure no groups or users ever have numbers for names, and you are safe

The same problem exists with ACO's. If you have your pages treed in controller/action format. When you go to put the home/home (controller/action) page into permisions, well.. the system will wonder why you are trying to make home a parent of itself. I have not figured out how to identify controllers or actions with numbers, so perhaps adding a convention will help.
Download code // set home action to be a child of the home controller
$aco->setParent('home/home', 'home'); 

So be careful when using Cake access control for User Permissions, it can work, you just have to be careful.

Putting this into your App

Well, perhaps a real world example of making sure access is controlled would look like this...

You would never write the following code out (I don't think). Likely you would want a full system where the following data is created using form input from a user.
Download code $aro = new Aro(); // users and groups
$aco = new Aco(); // controllers and actions

// add some users and groups to the system
// it is assumed you have your own table of user, with their own information
$aro->create( 1, null, 'John Smith' ); // 1=user_id, null=parent
$aro->create( 2, null, 'Millie Thompson');

$aro->create(0, null, 'Admins'); // group
$aro->create(0, null, 'Managers'); //group

//set John to be an admin
$aro->setParent('Admins', 1);
// set Millie to be an manager
$aro->setParent('Managers', 2);

$aco->create(0, null, 'Home/home');

In one of your controllers you can do something that looks like this
Download code $this->Acl->allow('Admins', 'Home/home', 'read');
$this->Acl->deny('Managers', 'Home/home');
There, now John can get into home/home and Millie cannot.

After you set up your data, this is practical code, that you might actually write. It will automatically allow or deny the logged in user access to a given action.
Download code class AppController extends Controller {
    
    var $components = array('Acl');

    function beforeFilter() {
        // next line will change depending on your auth system
        // basically getting the Id of the currently logged in user
        $user_id = $this->obAuth->getUserId(); 

        $page = $this->name.DS.$this->action; 
        $access = $this->Acl->check($user_id, $page, 'read');

        //access denied (if we are in Home/home, this is Millie)
        if ($access === false) { 
            echo "access denied";
            exit;
        }
        
        //access allowed (if we are in Home/home, this is John)
        else {
            echo "access allowed";
            exit;
        }
    }

}

I'll leave it up to you to set up your own permsissions, and groups in a real life system. This does give you a good overview of the concepts though.

There is an ACL management plugin on CakeForge which might help you. Currently it is still young and in development. It might help automate a lot of these things for you.

Comments 291

CakePHP team comments Author comments

Comment

1 The best ACL Tutorial

This is by far the best acl tutorial I've found, it is simple not to get you confused about aros and acos and very short to explain something that for long time has been a mistery to many people.
posted Tue, Mar 27th 2007, 12:45 by Boris Barroso

Comment

2 re the best ACL tutorial

This is by far the best acl tutorial I've found, it is simple not to get you confused about aros and acos and very short to explain something that for long time has been a mistery to many people.

yes! definitely. one of the best starter ACL lessons I've seen. A really good starter position that communicates the parts of ACL most useful to the most people.
posted Sun, Apr 8th 2007, 15:04 by Walker Hamilton

Question

3 I Wonder

Okay I think its clear now, but what if I want to put a user in 2 (or more) different permission groups? It probably will not work, right? I don't know, I still think this whole Access Control in CakePHP is to young to be used for bigger purposes.
posted Fri, Apr 13th 2007, 03:50 by David

Comment

4 Further reading...

Somewhere in cakePHP-land is a comment that refers to this article: http://dev.mysql.com/tech-resources/articles/hierarchical-data.html

Most of us have stored hierarchical data with just a parent_id (self join). The above article presents a different and vastly more optimal way to do this, but it's hard to wrap the brain around. In any event, that article explains how the hierarchy is mapped in cakePHP
posted Fri, Apr 13th 2007, 10:55 by Ben

Comment

5 I Wonder Reply

@David: Yes the lack of multiple parents is a bit of a downfall right now. Its been requested, I'm sure it will not be long before this feature is implemented. I think the big problem is this: If parent permissions conflict at all, how do you handle which one takes priority?
https://trac.cakephp.org/ticket/2191

posted Fri, Apr 13th 2007, 14:39 by Rob Conner

Comment

6 Re. Further reading...

posted Sat, Apr 14th 2007, 21:20 by Nate

Bug

7 Great article

Great article. Similar to the CakePHP manual, but this seemed easier to understand for some reason.

I did notice one bug (I think). In the last section, you have written:

$page = $this->name.DS.$this->action;
$access = $this->Acl->check($page, $user_id, 'read');

In the check function, I believe $page (an ACO) should be switched with $user_id (an ARO). Not 100% on this, but I think it's a small bug.

Anyway, great article!
posted Wed, Jun 13th 2007, 12:39 by Eric Farraro

Comment

8 reply to Great Article

In the check function, I believe $page (an ACO) should be switched with $user_id (an ARO). Not 100% on this, but I think it's a small bug. Yep thanks, I fixed it.
posted Thu, Jun 14th 2007, 09:42 by Rob Conner

Question

9 Im sure this is retardedness on my part

So, I cannot figure this out at all. First of all: this is a great article, very easy to read and understand.

Except, apparently, the "understand" part.

Regarding CakePHP 1.2. Questions:

1) The acl.php lib that contains the Acl class actually contains only a "AclComponent" class. Is this what is being used in Cake 1.2?

2) If yes to (1), then how are the $acl, $aco objects instantiated (or are they)? Something like

$acl = new AclComponent();
$aro = new $acl->Aro(); // this? or
// Create aro
$acl->Aro->create(1,null,'Admin Guy');

Confused!!

3) I tried fifty different combinaations of the code on this page and the code in (2) in my comment here and still have no aros created in my aro table.

I really am lost on this thing; nothing seems to be working. Arrgh!
posted Tue, Oct 23rd 2007, 15:32 by Jeffrey Silverman

Comment

10 Please help me to know about ACL

Please give me one lesson and example about ACL in cakephp, thanks.
posted Fri, Dec 21st 2007, 04:01 by one cart

Comment

11 ACM on CakeForge

Just a notice for those who read this great tutorial. I have ACM working with 1.2 currently in the trunk. Still have some features to add to make it fully usable as intended in CakePHP 1.2. Looking to do this while at CakeFest.
posted Tue, Jan 29th 2008, 18:37 by Ryan J. Peterson

Comment

12 Very beautiful Tutorial.

I have struggled with ACL for couple of days. Almost every tutorial I saw push me to *guess* some concepts by myself. Finally, I got a relatively clear idea about the ACL, which is exactly the same as you mentioned in the top paragraphs:

"Cake Acces control was not made specifically for User/Group permissions control. It is simply a generic access control system to be used for anything."

I might have not taken that much time thinking about the basic ACL design if I saw your stuff earlier.

As a complement, I understood the ACL by dividing the concepts for typical uses into two genres:

1. For Controller/Action level verification, which was summarized in this article.

2. For Record level verification, which usually use something like 'Model::id' as an alias to identify an aCo.

Finally, ACL is nothing but relations between tree-structured records. What is aRos, what is aCos, when will the objects be used and where will they be checked are full charged by designers.
posted Fri, Apr 18th 2008, 03:34 by Yifan Jiang

Question

13 Cannot Inherting Permission

This is nice tutorial for understanding acl as it helps me to understand the acl and permssion w.r.t to groups.

But I found a problem that, I think it cannot inherit permission from one group to other group.

Like if I have two groups under the root i.e
ROOT
1 admin
2 member

and suppose i have an acos

/
1 Posts/
2 Posts/lists

I have member test under admin group.

Now if I deny the permission to ROOT for acos Posts/lists or /

then acl will not inherit this permission to users test and it allow the access to Posts/lists

Is it not possible with acl?

if yes, please suggest how to do?

Also I want if permission to acos '/' is denied for any group then none of the resources should be accessible to that group unless and untill i assign the permsion to that group
posted Fri, Apr 18th 2008, 07:49 by Manoj

Login to Submit a Comment