DarkAuth v1.3 - the intro

» Page: 1 - the intro, 2 - the component, 3 - the setup

Update: I have ammended the component code, as it was not working with the RC of 1.2 only a small fix but necessary. Thanks to those of you who pointed the bug out to me!

This is an update to my original DarkAuth component (http://bakery.cakephp.org/articles/view/darkauth-another-way), with increased efficiency and easier access control. It works exactly how I want to, so it might not be your first choice, but it's a solid alternative to the inbuilt AuthComponent.

Main Features:

  • Per action / per controller / inline access control
  • Group support for HABTM and BelongsTo Group associations, or disable groups control completely.
  • A "super-user" functionality allowing one group automatic access granted
  • Optional tamper-proof Cookie support
  • Custom password hashing to suit your Model
  • Passes User Info and Access Matrix to view
  • Methods to access User Info / Access Matrix in Controller

Firstly thank you to everyone who encouraged me after the first release of DarkAuth. Looking back at it, it was flawed yet I got support from the community and have worked to better it.

So I'll start the article again with just how easy it is to use.

Let's say you have a SecretsController which you want to restrict access to:

Controller Class:

  1. <?php
  2. class SecretsController extends AppController {
  3.   var $name = 'Secrets';
  4.   var $_DarkAuth;
  5.  
  6. ...
  7.  
  8. }
  9. ?>

See what I did there? Now you'd have to be logged in to access this Controller. So, now you want to refine this to allow only logged on users that are a member of the group Admin or the group SecretKeepers. Easy!

Controller Class:

  1. <?php
  2. class SecretsController extends AppController {
  3.   var $name = 'Secrets';
  4.   var $_DarkAuth = array('required'=>array('Admin','SecretKeepers'));
  5.  
  6. ...
  7.  
  8. }
  9. ?>

Not bad eh? So moving on, by default your users if not allowed access will see your specified "deny" page, but you want them to be redirected back to /public. Again, straightforward.

Controller Class:

  1. <?php
  2. class SecretsController extends AppController {
  3.   var $name = 'Secrets';
  4.   var $_DarkAuth = array(
  5.          'required'=>array('Admin','SecretKeepers'),
  6.          'onDeny'=>'/public'
  7.       );
  8.  
  9. ...
  10.  
  11. }
  12. ?>

Now, any attempt to access your SecretsController will be presented with a login page if not logged in and if logged in but not a member of the group, will be redirected to /public.

This can be done per action as well, to further enhance the usefullness of the component. E.g. you have a DocumentsController which might be publically accessible but also might have some top secret documents in it. You only want members of the group TopBrass to be able to see these restricted documents.

Controller Class:

  1. <?php
  2.   function display($id=0){
  3.     $this->Document->id = $id;
  4.     $doc = $this->Document->read();
  5.  
  6.     if($doc['Document']['top_secret'] == true){
  7.        $this->DarkAuth->requiresAuth('TopBrass');
  8.     }
  9.     ...
  10.  
  11.   }
  12. ?>

Note that the function DarkAuth::requiresAuth() stops processing after you call it and will bring up an "access denied" view if authentication fails. So no need to exit().

Or more common if you wanted to show content based on whether authentication was present? The DarkAuth::isAllowed() function returns whether access is allowed, but doesn't stop processing:

Controller Class:

  1. <?php
  2.   if($this->DarkAuth->isAllowed(array('ChocolateLover'))){
  3.     $data = $this->CookieJar->findAll(array('Chocolate'=>true));
  4.   }else{
  5.     $data = $this->CookieJar->findAll(array('Chocolate'=>false));
  6.   }
  7. ?>

The final selling point (and most useful in my opinion) is the $_DarkAuth available in the View, automatically populated with the user info from the user model and the access control list. e.g.

  1. <?php
  2.   pr($_DarkAuth);
  3. ?>

Yields if logged in:

  1. array(
  2.       'User' => array(
  3.                       'id' => 1
  4.                       'username' => superstar
  5.                       'password' => abcdef1234567890abcdef1234567890
  6.                       'other_info' => Some data
  7.                 )
  8.   'Access' => array(
  9.                     'group_you_have_access_to' => 1
  10.                     'another_group_you_have_access_to' => 1
  11.                     'group_you_have_NO_access_to' => 0
  12.               )
  13. )

Which means you can do this:

View Template:

  1. <?php
  2. if(!empty($_DarkAuth['User'])){
  3.   echo "Some content for logged in people!";
  4. }
  5. if($_DarkAuth['Access']['some_group']){
  6.   echo "You have access to 'some_group'";
  7. }else{
  8.   echo "You don't have access to 'some_group'";
  9. }
  10. ?>

Convinced? I hope so. Now on the Code and Setup!

» Page: 1 - the intro, 2 - the component, 3 - the setup