14

I have successfully used Auth, but unfortunately, it seems that it does work only with Session. I want that if user checks "Remember Me" checkbox, I would use Cookie and he would be logged in for 2 weeks. I can't find anything in official book and in Google I found just few and not great blog posts. Is there any way to implement this without rewriting the core?

good_evening
  • 21,085
  • 65
  • 193
  • 298
  • 2
    Are you not interested in having this question answered anymore or what? You've given no feedback to any of the answers. – Hoff Sep 21 '12 at 14:20
  • You may want to take a look at https://github.com/delight-im/PHP-Auth which is both framework-agnostic and database-agnostic. – caw Sep 22 '16 at 03:02

8 Answers8

48

In your user controller:

public function beforeFilter() {
    $this->Auth->allow(array('login', 'register'));
    parent::beforeFilter();
}

public function login() {
    if ($this->request->is('post')) {

        if ($this->Auth->login()) {

            // did they select the remember me checkbox?
            if ($this->request->data['User']['remember_me'] == 1) {
                // remove "remember me checkbox"
                unset($this->request->data['User']['remember_me']);

                // hash the user's password
                $this->request->data['User']['password'] = $this->Auth->password($this->request->data['User']['password']);

                // write the cookie
                $this->Cookie->write('remember_me_cookie', $this->request->data['User'], true, '2 weeks');
            }

            return $this->redirect($this->Auth->redirect());

        } else {
            $this->Session->setFlash(__('Username or password is incorrect.'));
        }
    }

    $this->set(array(
        'title_for_layout' => 'Login'
    ));
}

public function logout() {
    // clear the cookie (if it exists) when logging out
    $this->Cookie->delete('remember_me_cookie');

    return $this->redirect($this->Auth->logout());
}

In the login view:

<h1>Login</h1>

<?php echo $this->Form->create('User'); ?>
    <?php echo $this->Form->input('username'); ?>
    <?php echo $this->Form->input('password'); ?>
    <?php echo $this->Form->checkbox('remember_me'); ?> Remember Me
<?php echo $this->Form->end('Login'); ?>

In your AppController:

public $components = array(
    'Session',
    'Auth',
    'Cookie'
);

public $uses = array('User');

public function beforeFilter() {
    // set cookie options
    $this->Cookie->key = 'qSI232qs*&sXOw!adre@34SAv!@*(XSL#$%)asGb$@11~_+!@#HKis~#^';
    $this->Cookie->httpOnly = true;

    if (!$this->Auth->loggedIn() && $this->Cookie->read('remember_me_cookie')) {
        $cookie = $this->Cookie->read('remember_me_cookie');

        $user = $this->User->find('first', array(
            'conditions' => array(
                'User.username' => $cookie['username'],
                'User.password' => $cookie['password']
            )
        ));

        if ($user && !$this->Auth->login($user['User'])) {
            $this->redirect('/users/logout'); // destroy session & cookie
        }
    }
}
Hoff
  • 1,762
  • 14
  • 27
  • 3
    I would feel quite uncomfortable knowing that my password, even encrypted, floats somewhere in a cookie. I think that in such a case, storing the username is enough. – nIcO Sep 19 '12 at 21:34
  • Keep in mind that it's the encrypted, salted, hash of your password. If that still keeps you on edge, your best bet is to have a randomly generated token to go along with the username. I personally wouldn't rely on just the username alone. – Hoff Sep 20 '12 at 01:12
  • 1
    You are right, actually I realized it afterwards. But anyway, I would prefer not to store anything related to the password in a cookie. I'm not sure if it is a kind of allergy, but this idea gives me goosebumps ;-) – nIcO Sep 20 '12 at 06:37
  • 4
    One other benefit of using the password like above as well is that if you change your password, it automatically invalidates the cookie on all devices forcing a relogin. :) – Hoff Sep 21 '12 at 14:19
  • Agree with @nlcO. I don't want to store such thing as password in cookie. It doesn't matter that it's hashed. Of course, storing only username is also bad, because user can edit cookie and he would be able to login to any account. This is a not good solution. – good_evening Sep 21 '12 at 14:25
  • @hey Actually the username would be encrypted as well in the cookie, so it wouldn't be that easy to edit it to set any other username. But like Hoff said, maybe passing a token along with the username would be a good idea. – nIcO Sep 21 '12 at 16:17
  • 2
    Doesn't seem like he's interested in getting much help, it's a shame these people took time out of their days to try and help. I'll remember to steer clear of @hey's questions in the future. – Hoff Sep 21 '12 at 18:31
  • @nIcO: I don't want to store username in cookie, I want that Cookie to always be different every time user logins. – good_evening Sep 22 '12 at 12:17
  • 2
    Thank you for the detailed answer! I used this in an application, but I believe that "$this->Auth->login($user)" should be "$this->Auth->login($user['User'])". Now it works perfectly! – Roel Dec 05 '13 at 14:51
  • @Hoff: Worked like a charm :) – Amuk Saxena Oct 04 '14 at 08:58
  • @Hoff Agree on your comment about invalidated cookies. However in this case that would never work with the code above. Since $user is expected to be filled the if-statement if($user && !$this->Auth....) will return false whenever your user-data gets changed. This will need another if/elseif to work properly. Something like this: else if(!$user){ // invalid cookie, delete it + redirect to login $this->Cookie->delete('remember_me_cookie'); $this->redirect(['controller' => 'users', 'action' => 'login']); } –  Jun 12 '15 at 13:08
  • @Jordy A little late to reply, but how so? The only fields we're using to fetch the user are the username and password, so only one of those fields would have to change to invalidate the cookie. – Hoff Feb 26 '16 at 17:12
6

See this URL i think it is very help full to you.

http://lecterror.com/articles/view/cakephp-and-the-infamous-remember-me-cookie

Or Try this

function login() {
    if ($this->Auth->user()) {
        if (!empty($this->data) && $this->data['User']['remember_me']) {
            $cookie = array();
            $cookie['username'] = $this->data['User']['username'];
            $cookie['password'] = $this->data['User']['password'];
            $this->Cookie->write('Auth.User', $cookie, true, COOKIE_EXPIRE);
            unset($this->data['User']['remember_me']);
        }

        $this->LogDetail->Write('activity','has logged IN');
        $this->redirect($this->Auth->redirect());
    }

    if (empty($this->data)) {
        $cookie = $this->Cookie->read('Auth.User');
        if (!is_null($cookie)) {
            if ($this->Auth->login($cookie)) {
                $this->Session->destroy('Message.Auth'); # clear auth message, just in case we use it.
                $this->LogDetail->Write('activity','has been authenticated via cookie and is now logged IN');

                $this->redirect($this->Auth->redirect());
            } else {
                $this->LogDetail->Write('activity','attempted to gain access with an invalid cookie');
                $this->Cookie->destroy('Auth.User'); # delete invalid cookie

                $this->Session->setFlash('Invalid cookie');
                $this->redirect('login');
            }
        }
    }
}
Abid Hussain
  • 7,724
  • 3
  • 35
  • 53
  • 9
    I would feel quite uncomfortable knowing that my password, even encrypted, floats somewhere in a cookie. I think that in such a case, storing the username is enough. – nIcO Sep 19 '12 at 21:35
3

Remember me is nothing else but session identified with a cookie, but cookie lifetime set to infinity. Look at Config/core.php for session cookie lifetime.

sibidiba
  • 6,270
  • 7
  • 40
  • 50
  • 3
    Cookies lifetime is not enough. You would also have to make the sessions last that long on the server. – nIcO Sep 21 '12 at 16:26
0

I think you need to know about CakePHP Security levels. Try to lower the security of your cakePHP. CakePHP's Config variables documentation. I had written a blog about it also a long ago.

Nehal
  • 1,004
  • 1
  • 10
  • 33
0

you can try this

if ($this->Auth->login()) 
        {
            if (!empty($this->data['User']['remember']))
            {
                $cookie = array();
                $cookie['login'] = $this->data['User']['login'];
                $cookie['password'] = $this->data['User']['password'];
                                    $cookie['language'] =$this->data['User']['language'];
                $this->Cookie->write('Auth.projectname', $cookie, true, '+1 years');                                                        
                unset($this->data['User']['remember']);                                        
munsifali
  • 1,732
  • 2
  • 24
  • 43
0
 public function admin_login() {
        $this->layout = 'admin_login';
        if (count($this->Session->read("Auth.User"))) {
            $usr = $this->Session->read("Auth.User");
            if ($usr['role'] == 'A' || $usr['role'] == 'RA' || $usr['role'] == 'MAfA' || $usr['role'] == 'Af' || $usr['role'] == 'FAA')
                return $this->redirect(array('controller' => 'dashboard', 'action' => 'view'));
        }
        if ($this->request->is('post')) {

            if ($this->request->data['User']['remember_me']=="1") {
//                pr($this->request->data);
//                die('sdd');


                $this->Cookie->write('username', $this->request->data['User']['username'], true, '1 year');
                $this->Cookie->write('password', $this->request->data['User']['password'], true, '1 year');
            } else {
                $this->Cookie->destroy();
            }
            /*
             * Check if email or username is passed in form
             */
            $uname = $this->request->data['User']['username'];
            //login via email
            if (filter_var($uname, FILTER_VALIDATE_EMAIL)) {
                $u = $this->User->findByemail($uname);
            } else { //login via username
                $u = $this->User->findByusername($uname);
            }
            if ($u) {
                $this->request->data['User']['username'] = $u['User']['username'];
                /*                 * *
                 * Error if user is not active
                 */
                if ($u['User']['user_status'] != 'active') {
                    $this->Session->setFlash(__('Sorry! Your account is not active.'), 'default', array('class' => 'alert alert-danger'));
                } elseif ($this->Auth->login()) { //if logged in
                    $user_caps = $this->fetchCapabilitiesByRole($u['User']['role']);
                    $this->Session->write("Auth.User.privileges", array('capabilities' => $user_caps['capabilities'], 'geo_areas' => array()));
                    if ($u['User']['role'] == 'A' || $u['User']['role'] == 'RA' || $u['User']['role'] == 'Af' || $u['User']['role'] == 'MAfA' || $u['User']['role'] == 'FAA')
                        return $this->redirect(array('controller' => 'dashboard', 'action' => 'view'));
                    return $this->redirect($this->Auth->redirect());
                }else { //if invalid
                    $this->Session->setFlash(__('Invalid username or password.'), 'default', array('class' => 'alert alert-danger'));
                }
            } else {//if user does not exists
                $this->Session->setFlash(__('User does not exists.'), 'default', array('class' => 'alert alert-danger'));
            }
        }
    }
Ashish Pathak
  • 827
  • 8
  • 16
-1

It's been a while since the question was answered but hopefully this can help to ones that come after me.

I've written short walkthrough on how to setup 'remember me' functionality using Auhenticate Plugin from Ceeram

More info here: http://mirkoborivojevic.com/posts/2013/08/10/setup-remember-me-functionality-in-cakephp/

Community
  • 1
  • 1
Borivojević
  • 368
  • 2
  • 5
  • 12