obAuth Simple Authentication

By Steve Oliveira (coeus)
Authenticate your users and secure your controller actions from users belonging to certain groups. Or simply secure your controller actions to let any authenticated user to access it.

How to use: http://bakery.cakephp.org/articles/view/121
Some features:
1. User authentication
2. User groups supported
3. Protect action access with 1 line of code

Component Class:

Download code <?php 

class obAuthComponent extends Object 
{

    
/* Component config variables */
    
var $user_model "User";
    var 
$group_model "Group";
    var 
$user_fields = array('id' => 'id''username' => 'username''password' => 'password''group_id' => 'group_id');
    var 
$group_fields = array('id' => 'id''name' => 'name');
    var 
$components = array('Session');
    var 
$login_page 'users/login'// login action
    
var $logout_page null// Page to redirect to when user logs out
    
var $deny_page null// Page to redirect if you deny access but don't want take user to login page
    
var $sesskey "mYpERsOnALhaSHkeY";

    
/* Don't modify these variables */
    
var $last_page null;
    var 
$user null;
    var 
$controller;

    function 
startup(&$controller)
    {
        
$this->controller $controller;
        if (
$this->Session->valid() &&  $this->Session->check($this->sesskey))
        {
            
$this->user $this->Session->read($this->sesskey);
        }
        
$this->controller->set('obAuth'$this->user);
    }

    
// Method to check if user is logged. 
    
function login($data
    {
    
        
$username $data["{$this->user_fields['username']}"];
        
$password $data[$this->user_fields['password']];
        
$conditions = array($this->user_model.".".$this->user_fields['username'] => $username$this->user_model.".".$this->user_fields['password'] => md5($password), $this->user_model.".active" => 1);
        
$user $this->controller->{$this->user_model}->find($conditions);

        if (empty(
$user)) {
            return 
false;
        } else {
            
$sessdata["{$this->user_model}"]['id'] = $user["{$this->user_model}"]["{$this->user_fields['id']}"];
            
$sessdata["{$this->user_model}"]['username'] = $user["{$this->user_model}"]["{$this->user_fields['username']}"];
            
$sessdata["{$this->user_model}"]['password'] = $user["{$this->user_model}"]["{$this->user_fields['password']}"];
            
$sessdata["{$this->group_model}"]['id'] = $user["{$this->group_model}"]["{$this->group_fields['id']}"];
            
$sessdata["{$this->group_model}"]['name'] = $user["{$this->group_model}"]["{$this->group_fields['name']}"];
            
$sessdata["{$this->user_model}"]['login_hash'] = md5($this->sesskey $sessdata["{$this->user_model}"]['username'] . $sessdata["{$this->user_model}"]['password'] . $sessdata["{$this->group_model}"]['id']);
            
$this->Session->write($this->sesskey$sessdata);

            return 
true;
        }
    }

    
// Logout user and destroy cookie
    
function logout($redirect=null
    {
        
$this->user null;
        
$this->Session->delete($this->sesskey);
        
$page = (!empty($redirect)) ? $redirect $this->logout_page;
        
$this->controller->redirect($page);
    }

    
// Check is user is part of usergroup specified
    
function lock($groups=null$redirect=null)    
    {

        
$hasAccess false;

        
// User page tracker
        
if ($this->controller->action != "login")
        {
            
$this->last_page $this->controller->here;
        }

        if (!empty(
$this->user)) 
        {
            if (!empty(
$groups))
            {
                foreach (
$groups as $group
                {
                    if (
$this->user["{$this->group_model}"]['id'] == $group || $this->user["{$this->group_model}"]['name'] == $group)
                        
$hasAccess true;
                }
            }
            else 
            {
                
$hasAccess true;
            }
        }

        if(!
$hasAccess
        {
            
$page = (!empty($redirect)) ? $redirect $this->login_page;
            
$this->controller->redirect($page);
        } 

    }

    function 
deny($redirect=null)
    {
        
$page = (!empty($redirect)) ? $redirect $this->deny_page;
        
$this->controller->redirect($page);
    }

    function 
getUserId()
    {
        return (!empty(
$this->user)) ? $this->user["{$this->user_model}"]['id'] : false;
    }

    function 
getGroupId()
    {
        return (!empty(
$this->user)) ? $this->user["{$this->group_model}"]['id'] : false;
    }
}

?>

 

Comments 130

CakePHP Team Comments Author Comments
 

Question

1 Question about the lock method

I have a couple of questions about the lock method:

I see where the $usergroup and $sesskey variables are assigned, but don't see them used anywhere.

Secondly, I'm unclear about what this bit of code does in the lock method:

// User page tracker
if ($this->controller->action != "login")
{
$this->last_page = $this->controller->here;
}

One last question: where are the getUserId and getGroupId methods used? I searched around and didn't come up with anything.

Thanks!
Posted Nov 15, 2006 by Don Voita
 

Bug

2 Bugs

I see where the $usergroup and $sesskey variables are assigned, but don't see them used anywhere.
I ran into that too. The usergroup line is just plain wrong - $this->user is an array, not an object, and it actually generates an error anyway. Delete it.

$sesskey is used when building the session data or reading from it, but as you say, it's not used in lock(), so delete it.

As for getUserId etc, they could be used in login(), but it's probably faster to leave that lookup inlined as it is. I don't know why I'd need them apart from that.
Posted Nov 16, 2006 by Marcus Bointon
 

Comment

3 Bug fix

Thanks for the input guys.

When I released this component there were unfinished parts. For example the $this->last_page part is supposed to store the last page the user visited. For example, if a user tries to access "add members" section, they'll first be redirected to login page, once they login, they'll be then redirected to that page they were trying to access. This is still unfinished.
Posted Nov 22, 2006 by Steve Oliveira
 

Bug

4 Sql Injection Fix

Although this may have only affected me, I seem to have been able to "hack" my own page via SQL injections. I fixed it by replacing the $conditions line, with this line

$conditions = array($this->user_model.".".$this->user_fields['username'] => $username, $this->user_model.".".$this->user_fields['password'] => md5($password), $this->user_model.".active" => 1);
Posted Dec 5, 2006 by Carlo
 

Comment

5 Make sure to exit after redirects

Make sure to call exit after redirects, especially in the lock method.
Posted Dec 12, 2006 by Don Voita
 

Comment

6 SQL Injection Fix

Thanks for pointing that out.
Posted Dec 13, 2006 by Steve Oliveira
 

Question

7 Session error

I'm getting session errors when I follow the tutorial, any solutions?:
Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at /Library/WebServer/Documents/cake_1.1.12.4205/ngo_reservation/controllers/components/ob_auth.php:118) in /Library/WebServer/Documents/cake_1.1.12.4205/cake/libs/session.php on line 146
Posted Dec 31, 1969 by Jason
 

Comment

8 Session fix

Jason, try removing any spaces before and after the php code in the ob_auth.php file.
Posted Dec 31, 1969 by Thomas Chapin
 

Comment

9 Cake 1.2.x Error

I'm using Cake 1.2.x

Getting an Error Undefined property: obAuthComponent::$User [CORE\app\controllers\components\ob_auth.php, line 47]
I'm having a bit of trouble trying to figure out how to fix this.
Posted Mar 14, 2007 by Rob Conner
 

Question

10 Questions about deny() and hashes..

I like very much this simple authentication method.

I have a few questions:
  • what's the aim of deny() function? I think it should be used in lock() when $hasAccess is false...
  • Why you save 'login_hash'? how can it be used?
  • Why user information are saved in a hash session variable ($sesskey)? Isn't better save it in a well-known session variable (for example $sesskey='profile'), so it's simply accessible in the whole app through session helper? Are there security issues?

Thank you for this useful work.
Carlo.
Posted Sep 26, 2007 by Carlo S.
 

Comment

11 RE Questions about deny() and hashes

The deny function and login_hash were meant for future updates, but I hadn't gotten around to updating the component. The deny function is supposed to be used in the lock function.

As for the user information, you can access all of the user information through the $this->obAuth->user variable in the controller you're working in.

I should be updating this component soon.
Posted Oct 3, 2007 by Steve Oliveira
 

Comment

12 Cake 1.18

Hi Steve,

I've read on the explanation page that this component stops working with Cake 1.18. Are you planning any fixes/updates?

thanks
Posted Nov 15, 2007 by Bo