Real World Access Control

By Rob Conner (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 Mar 27, 2007 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 Apr 8, 2007 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 Apr 13, 2007 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 Apr 13, 2007 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 Apr 13, 2007 by Rob Conner
 

Comment

6 Re. Further reading...

Posted Apr 14, 2007 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 Jun 13, 2007 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 Jun 14, 2007 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 Oct 23, 2007 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 Dec 21, 2007 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 Jan 29, 2008 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 Apr 18, 2008 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 Apr 18, 2008 by Manoj
 

Comment

14 reply to Cannot Inherting Permission

@Manoj - there is no inheritance ability in 1.1 ACL all all. I'm not sure about 1.2, I heard it was in the plan, I do not know if it's been added at all.
Posted May 28, 2008 by Rob Conner
 

Question

15 How to configure ACL if we are using path admin/*

Hi, Firstly thanks to Rob Conner for putting up such a great tutorial regarding ACL.

I have 3 questions which I am hoping will get response from you guys

Question 1:
How to use ACL with admin/* is enabled for administrators. So for example if I have created to user login path one is users/login for normal users and anothers admin/users/login then how ACL will come into action for such kind of controller/actions?

Question 2:
It seems that ACL only works for index,add,create,delete,edit actions and controller. What if we are using some other kind of functions for example xx_index,xx_add,xx_edit,xx_view etc - Will ACL work in this situation?

Question 3:
It seems we require allow/deny for each and every controller manually

$this->Acl->allow('Admins', 'Home/home', 'read');
$this->Acl->deny('Managers', 'Home/home');

Suppose if we require in future that Manager also access to read action of home contrller than we have to make changes manually to the above code which is not good. Is there any way to make it dynamic so that we can controle it from from end which action or controller will be accessed by which user or group ?

I
Posted May 31, 2009 by Sukhjinder
 

Comment

16 you will understand ACL of Cake

I think that if you finish to read the chapter 8 of Book -- Practical CakePhp projetcs and practice the code, you will totally understand ACL of Cake. This is a good example, except the Group should be set to tree.
Posted Jun 15, 2009 by Jason Yan