Qarchli Ismail
Qarchli Ismail

Reputation: 157

Authentication using Cakephp and PhoneGap

I am working on an application using Cakephp on the server side and PhoneGap at the client Side, with JSON as a intermediate to access the server side.

Now, I am working specifically on a login form where the user needs to enter his/her username and password. I put in my controller the following:

public function api_login() {

    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Headers: Authorization");

    if ($this->request->data && isset($this->request->data['username']) && isset($this->request->data['password'])) {
        $arrUser = $this->User->find('all',array(
            'conditions'=>array(
                'username'=> $this->request->data['username'],
                'password' => $this->request->data['password']
            )
        ));

        if (count($arrUser) > 0 ) {
            $this->Session->write('Auth.User',$arrUser[0]['User']);
            $arrReturn['status'] = 'SUCCESS';
            $arrReturn['data'] = array('loginSuccess' => 1,'user_id' => $arrUser[0]['User']['id'] );

        }
        else {
            $arrReturn['status'] = 'NOTLOGGEDIN';
            $arrReturn['data'] = array( 'loginSuccess' => 0 );
        }
    } else {
        $arrReturn['status'] = 'NOTLOGGEDIN';
        $arrReturn['data'] = array( 'loginSuccess' => 0 );
    }
    echo json_encode($arrReturn);
}

and in the client side, I am retrieving what JSON encoded as follows:

<script>
    $(document).ready(function(){
        $('form').on('submit',function(e){
            e.preventDefault();
            $username = $("#form-username").val();
            $password = $("#form-password").val();
            $.ajax({
                url : "http://localhost/teslaphonegap_cakephp/" + 'login.json',
                cache : false,
                data : {
                    'username' : $username,
                    'password' : $password },
                dataType : 'json',
                type : 'POST',
                success : function(result) {

                    if(result.status=="SUCCESS"){
                        alert("success");
                        console.log(result);
                    }else{

                        alert("username or pass are wrong");
                        console.log(result);
                    } },
                error : function(xhr, status, err) {
                    alert("ERROR");
                }
            });
        });
    });
</script>

and in my Model I used the beforeSave() in order to hash the passwords before they get added at the very beginning in the Database:

public function beforeSave($options = array()) {

    $value=$this->data['User']['password'];
    $encrypted = Security::encrypt($value, Configure::read('Security.cipherCriptKey'));
    $this->data['User']['password'] = $encrypted;
    return true;
} 

Now, when I try to login it always returns the error message because it compares a value that is unhashed with other values that are already hashed in my Database. How can I solve this issue? I used the afterFind() but it didn't work:

public function afterFind($results, $primary = false) {

    foreach ($results as $key => $val) {            
        if(isset($val['User']['password'])){
            $results['User']['password'] = Security::decrypt($val['User']['password'], Configure::read('Security.cipherCriptKey'));
        }
        return $results;
    }        
}

-- EDIT

and in my core.php I used the following:

    Configure::write('Security.cipherCriptKey','su0HKssPmdbwgK6LdQLqzp0Y7zOmyaTI');

Upvotes: 1

Views: 93

Answers (1)

Inigo Flores
Inigo Flores

Reputation: 4469

First of all, your afterFind() callback won't work as expected.

The line

        $results['User']['password'] = Security::decrypt($val['User']['password'], Configure::read('Security.cipherCriptKey'));

should be written as

        $results[$key]['User']['password'] = Security::decrypt($val['User']['password'], Configure::read('Security.cipherCriptKey'));

However, changing this won't fix your problem. If you search the database for a record with a password matching $this->request->data['password'], it will return no results. Note that the password in the database is hashed.

You have to fetch the record from table users that matches $this->request->data['username'], decrypt the value of field password and compare it against $this->request->data['password'].

Decryption is already taken care by afterFind(), so your code could be written as follows:

if ($this->request->data && isset($this->request->data['username']) && isset($this->request->data['password'])) {
    $arrUser = $this->User->find('first',array(
        'conditions'=>array(
            'username'=> $this->request->data['username'],
        )
    ));

    if ($this->request->data['password'] == $arrUser['User']['password']) { 
        $this->Session->write('Auth.User',$arrUser['User']);
        $arrReturn['status'] = 'SUCCESS';
        $arrReturn['data'] = array('loginSuccess' => 1,'user_id' => $arrUser['User']['id'] );
        //rest of your code

Upvotes: 1

Related Questions