DarkAuth - another way...

By Chris Walker aka "theChrisWalker"
I wrote this initially for Cake 1.1 - basing it on ideas from "obAuth" by Steve Oliveira, but upgraded it to 1.2 rather than using the built in Auth component, mostly because this works how I want it to and, once setup, is really easy to use.

Main Features:

- Per action / per controller / inline access control
- Optional Group support for HABTM and User BelongsTo Group associations
- A "super-user" functionality allowing one group automatic access granted
- Optional tamper-proof Cookie support
- Custom password hashing to suit your Model
I'm fairly new to CakePHP and I went for the stable release, and immediately wanted to do User Authentication. It's almost the first thing I build into any project. CakePHP 1.1 didn't have it, so I built my own.

This is mainly based on "obAuth" by Steve Oliveira. It was those ideas that formed the basis for this component. It includes a lot of the functionality that was designed into obAuth but never completed and also now ammended to work with CakePHP 1.2.

As soon as I switched to CakePHP 1.2 and wanted the same great features I built into the original and the same easy access control. So, I rewrote it and here's the result.

Firstly I'll show you how easy it is to work with.

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

Controller Class:

Download code <?php 
class SecretsController extends AppController {
  var 
$name 'Secrets';

  var 
$DarkAuth_requiresAuth = array('Secret Keepers','Super Cool People');

...

}
?>


Notice the one-liner? This will restrict access to the controller to Users who are memebrs of either the group 'Secret Keepers' or the group 'Super Cool People'.

Easy huh? However, I think Cake's own is that easy as well, so lets look at some more functionality.

How about you have a DocumentsController that only certain people can add to?

Controller Class:

Download code <?php 
class DocumentsController extends AppController {
  var 
$name 'Documents';

  function 
add(){
    
$this->DarkAuth->requiresAuth = array('Secret Makers');
    
    ...
  }

...

}
?>


Now that was easy, only memebers of the group 'Secret Makers' will have access.

How about your DocumentsController that has some Top Secret stuff in it and you want to restrict access? We could add to our "view" action some simple code:

Controller Class:

Download code <?php 
  
function view($id){
    
$this->Document->id $id;
    
$doc $this->Document->read();

    if(
$doc['Document']['top_secret'] == true){
       
$this->DarkAuth->requiresAuth('Top Brass');
    }
    ...

  }
?>


Note that the function "requiresAuth()" stops processing after you call it and will bring up an "access denied" view if authentication fails.

What if you wanted not to fail after but to redirect somewhere else?

Controller Class:

Download code <?php 
$this
->DarkAuth->requiresAuth('Top Brass');
?>


Or more common if you wanted to show content based on whether authentication was present?

Controller Class:

Download code <?php 
  
if($this->DarkAuth->isAllowed(array('Chocolate Lover'))){
    
$data $this->CookieJar->findAll(array('Chocolate'=>true));
  }else{
    
$data $this->CookieJar->findAll(array('Chocolate'=>false));
  }
?>


The "isAllowed()" function will return true/false but not halt processing.

The final selling point (in my opinion)! $DarkAuth_User available in the View, automatically populated with the user info from the user model. e.g.

View Template:

Download code
pr($DarkAuth_User);


Yields (if logged in, if not logged in the variable is null):

Download code
array(
  'id' => 1
  'username' => "superstar"
  'password' => "abcdef1234567890abcdef1234567890"
  'other_info' => "Some data"
)


Which means you can do this:

View Template:

Download code
if(!empty($DarkAuth_User)){ 
  echo "Some content for logged in people!";
}


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

Page 2: The Component Code

Comments 617

CakePHP team comments Author comments

Comment

1 Thanks for a great article

A very thorough and helpful article. Good job in creating it in a way to suit the most amount of people.

However the one thing that will probably keep me from using it, is that my tastes are a bit opposite to yours. I prefer to define access names and check for those. I have predefined what access the groups have and check if a user has access through it's group.

I dont know if that is clear, but in your example, I would define that the SecretsController requires "Secret level access" and either the (or one of the) group that logged in user belongs to has access to it or not.

The gain from doing it this way is that I don't have to edit my secrets controller when adding,removing or editing groups . This I feel is more inline with the cake behavior of controllers.

Anyways, just wanted to offer my 2 cents and thank you for your contribution.
posted Tue, Feb 19th 2008, 02:52 by Alexander

Comment

2 Thanks

Thanks for the article - haven't digested it all yet, but like you the first thing I do is user auth in my apps. I'll give this a look
posted Tue, Feb 19th 2008, 18:28 by Brit Gardner

Question

3 it doesnt work

Hi,

I'm newbie in cakePHP and I think this article is written in very bad way. Why you didn't create COMPLETE GUIDE ? You wrote sentenses like: "Look at the Cake Manual for how to setup the Models for these tables.", "var $uses = array ('YOUR_MODEL_FOR_USERS'); ", and so on.

I'm newbie and I don't know what you mean. I looked at manual but it still doesn't work !!!

I have errors like : "SQL Error: 1054: Unknown column 'User.email' in 'where clause'", when I go to "cake_1.2beta/users/_login" it has error "Error: UsersController::_login() cannot be accessed directly.", and so on ...

I know that I mistakely did something, BUT YOU CAN WRITE ARTICLES MORE UNDERSTAND ...

What do you recommend me ?

thx
posted Fri, Feb 29th 2008, 03:36 by greppi

Comment

4 RE it doesnt work

I don't think its really necessary to tell the author his article isn't written well when the problem is obviously your lack of understanding CakePHP, as you admitted. If you are unfamiliar with the framework then a good place to start would be the docs. Either http://tempdocs.cakephp.org/ for the BETA or http://manual.cakephp.org/ for the stable release.

We are all newbies once and I know exactly how you feel, when I first started I was completely lost (coming from an ASP.NET background to PHP), but it is through the docs and articles like these that I have quickly picked it up.

As far as the problems you have, the SQL error means you have not created the correct columns in your table.

"Look at the Cake Manual for how to setup the Models for these tables." - Means just that - go check out the documentation and samples that are available and you will quickly see how to implement the models for your application.

Anyways, I for one would like to say thank you to the author, I am in the middle of implementing this in my current project and it's looking promising. Great job
posted Sun, Mar 2nd 2008, 13:22 by Wayne

Comment

5 RE RE it doesnt work

That's true, but ... Anyway, I'll study more, ...
posted Tue, Mar 4th 2008, 14:15 by greppi

Question

6 Redirect after login form broken

I am trying to get DarkAuth to work with Cake 1.2.0.6311. It is looking promising... but right now I am stuck.

I followed all your steps and am using your login and deny pages. DarkAuth is protecting a test controller, but after completing the login form I am not getting the page of the controller action. All I get is the Debug info, which is shown at the bottom of the page with the CakePHP default views. After reloading or loading another action manually, I get the correct behavior.

As I have by now started with freshly baked controllers/views a couple of times I begin to wonder whether this is an Apache or DarkAuth problem.

Any ideas?

Thanks for the nice component!
posted Mon, Mar 10th 2008, 12:31 by Stephan

Question

7 RE Redirect after login form broken

I followed all your steps and am using your login and deny pages. DarkAuth is protecting a test controller, but after completing the login form I am not getting the page of the controller action.

I had the same problem, I found a workaround by removing the line
exit();
from the _login() function in app_controller.php and sobstituting it with:
$this->redirect('./');

Hope that works
posted Sat, Mar 15th 2008, 14:10 by Stefano Pallicca

Question

8 DarkAuth for home.ctp

I'm trying to implement this auth system in one of my projects. Now I have a question: I'm trying to add authentication to my home page (that is home.ctp). Now, this page has no controller, so how can darkauth e aware of it?

I'll try to describe my problem more in depth: I've successfully applied darkauth to a User model, so if I try to access /cake/users I get my login screen, and everything works fine.
Now, if I want to go back to my site homepage, located in /cake, I get an error:

Undefined property: PagesController::$User [APP/controllers/components/dark_auth.php, line 248]

Line 248 says:

$check = $this->controller->{$this->user_model_name}->find($conditions);

And I can understand the error, since home.ctp has no controller associated.
home.ctp shows correctly if I logout from darkauth...
What if I'd like to show a different content on the home page for logged/unlogged users? Is it possibile?
Thanks in advance and sorry for the long post.
posted Sat, Mar 15th 2008, 14:21 by Stefano Pallicca

Comment

9 RE RE Redirect after login form broken

I followed all your steps and am using your login and deny pages. DarkAuth is protecting a test controller, but after completing the login form I am not getting the page of the controller action.

I had the same problem, I found a workaround by removing the line
exit();
from the _login() function in app_controller.php and sobstituting it with:
$this->redirect('./');

Hope that works



First, I would like to thank Chris Walker or this wonderful component. It is simple, straightforward and fully working.

My approach to the problem above is to include this line:

$this->redirect($this->referer());

just before the exit();

This way, the user is redirected to the url he wants to.
posted Mon, Mar 17th 2008, 06:38 by mike stivaktakis

Comment

10 Re DarkAuth for home.ctp

Firstly, thanks to you all for your comments, suggestions and encouragement. Particularly the first comment by Alexander: "Good job in creating it in a way to suit the most amount of people." This is exactly what I wanted to do but you can never tell!

In response to Stefano Pallicca:
I'm trying to implement this auth system in one of my projects. Now I have a question: I'm trying to add authentication to my home page (that is home.ctp). Now, this page has no controller, so how can darkauth e aware of it?

I'll try to describe my problem more in depth: I've successfully applied darkauth to a User model, so if I try to access /cake/users I get my login screen, and everything works fine.
Now, if I want to go back to my site homepage, located in /cake, I get an error:

Undefined property: PagesController::$User [APP/controllers/components/dark_auth.php, line 248]

Line 248 says:

$check = $this->controller->{$this->user_model_name}->find($conditions);

And I can understand the error, since home.ctp has no controller associated.
home.ctp shows correctly if I logout from darkauth...
What if I'd like to show a different content on the home page for logged/unlogged users? Is it possibile?
Thanks in advance and sorry for the long post.


It looks like you haven't added the

$uses = array('User');

line to your AppController, that's what I would check first.
The controller your home.ctp view uses is the PagesController, which doesn't appear to have access to your User model. In an update I will get DarkAuth to load it automagically if needed, but for now you must add it to your AppController class.

posted Fri, Apr 4th 2008, 07:28 by Chris Walker

Comment

11 Re DarkAuth for home.ctp

It looks like you haven't added the
$uses = array('User');


That was the point: I added 'user' (lowercase), that's why it didn't work! Thanks for the tip and keep improving darkauth!
posted Sat, Apr 5th 2008, 07:24 by Stefano Pallicca

Comment

12 destroyDate() destroys all session data.

When the function destroyData() is called, it destroys all session data, while it should only delete the session data set by DarkAuth.

To fix this, replace:
$this->Session->destroy($this->secure_key());
by
$this->Session->delete($this->secure_key());
posted Sat, Apr 26th 2008, 05:01 by Tijmen

Comment

13 RE destroyData()

When the function destroyData() is called, it destroys all session data, while it should only delete the session data set by DarkAuth.

To fix this, replace:
$this->Session->destroy($this->secure_key());
by
$this->Session->delete($this->secure_key());


Thanks, I've updated this in the article. Also I have updated the code in a much bigger way, adding some new features and improving efficiency, and have posted a new article with it - which hasn't been moderated yet. Sometime soon it should be available at: http://bakery.cakephp.org/articles/view/darkauth-v1-3-an-auth-component
posted Sat, Apr 26th 2008, 15:14 by Chris Walker

Question

14 New Code


Thanks, I've updated this in the article. Also I have updated the code in a much bigger way, adding some new features and improving efficiency, and have posted a new article with it - which hasn't been moderated yet. Sometime soon it should be available at: http://bakery.cakephp.org/articles/view/darkauth-v1-3-an-auth-component


Hi Chris, any ideas when the article might be moderated? I am quite interested in the updated code for my new project :)
posted Fri, May 2nd 2008, 08:00 by Wayne

Comment

15 RE New Code


Hi Chris, any ideas when the article might be moderated? I am quite interested in the updated code for my new project :)


I have no idea, so I put a copy of the article on my own website... http://thechriswalker.net/darkauth-1. Enjoy.
posted Fri, May 2nd 2008, 10:09 by Chris Walker

Login to Submit a Comment