CakePHP Authentication on REST API

13,854

Solution 1

Alright, first a clarification about how AuthComponent::login works. In Cake 2.x that method does not do any authentication, but rather creates the Auth.User array in your session. You need to implement the actual authentication yourself (the User model is a natural place to do this). A basic authentication method might look like this:

App::uses('AuthComponent', 'Controller/Component');
public function authenticate($data) {
    $user = $this->find('first', array(
        'conditions' => array('User.login' => $data['login']),
    ));
    if($user['User']['password'] !== AuthComponent::password($data['password']) {
        return false;
    }

    unset($user['User']['password']);  // don't forget this part
    return $user;
    // the reason I return the user is so I can pass it to Authcomponent::login if desired
}

Now you can use this from any controller as long as the User model is loaded. You may be aware that you can load it by calling Controller::loadModel('User').

If you want to authenticate every request, then you should then put in the beforeFilter method of AppController:

public function beforeFilter() {
    $this->loadModel('User');
    if(!$this->User->authenticate($this->request->data)) {
        throw new UnauthorizedException(__('You don\'t belong here.'));
    }
}

All of the above assumes that you pass POST values for login and password every time. I think token authentication is definitely the better way to go, but for getting up and running this should work. Some downsides include sending password in cleartext (unless you require ssl) every request and the probably high cpu usage of the hashing algorithm each time. Nevertheless, I hope this gives you a better idea of how to do authentication with cakephp.

Let me know if something needs clarifying.

Update: Since posting this, I found out that you can actually use AuthComponent::login with no parameters, but I am not a fan of doing so. From the CakePHP documentation:

In 2.x $this->Auth->login($this->request->data) will log the user in with 
 whatever data is posted, whereas in 1.3 $this->Auth->login($this->data) 
 would try to identify the user first and only log in when successful.

Solution 2

AuthComponent::login() creates a session variable that stores the user data, so say you had data that was something like.

$data = array('User' => array('id' => 1, 'username' => 'johndoe'));

Then you would use

$this->Auth->login($data);

And access the data with

$this->Auth->user('User');

To get the user id

$this->Auth->user('User.id');

In your AppControllers beforefilter put $this->Auth->deny(); that will deny all actions to someone who is not logged in. Then in each controllers before filter you want to $this->Auth->allow(array('view')); 'view' being the name of an action you want to be public.

http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html

Solution 3

Cakephp 2.X, After lots of research about this on internet I did not find any satisfactory answer So I found a way myself to do this. May be this answer will help some folks in future. This answer is only applicable for REST API's in cake php.

Add following line in your logic action of REST API before checking for the $this->Auth->login().

 $this->request->data['User'] = $this->request->data ; 
 if($this->Auth->login()){
    echo "Hurray You are logged In from REST API.";
 }
 else
 {
    throw new UnauthorizedException(__('You don\'t belong here.'));
 }

Desciption : As @threeve said in one of the answers that $this->Auth->login() does not do any authentication itself. but rather creates the Auth.User array in your session. For Authentication we require our $this->request->data to be inside User array since User is the model which will check the Credentials in Database. Therefore we have to pass the data to Auth as it is required when not using REST API's. Rest of the things will be handled by Cake and Auth itself.

Any enhancements or suggestions on this answer are most welcome.

Share:
13,854
Christopher Francisco
Author by

Christopher Francisco

Updated on June 28, 2022

Comments

  • Christopher Francisco
    Christopher Francisco almost 2 years

    So I'm creating a REST API for a web app I'm developing, and I know the basic ways for authentication are either sending the credentials on each request or sending a token.

    Since I have never used token before, I think I may send the credentials for each request. The point is I can't find any examples on how to handle this in the controller. Would it be something like this?

    public function api_index() {
        if(!$this->Auth->login()) return;
    
        $this->set(array(
            'models' => $this->Model->find('all'),
            '_serialize' => array('models')
        ));
    }
    

    I don't really think this is the way AuthComponent::login() works, can I get some directions here please?