This has been an issue for me way too long.
I always hated the fact that users are logged out almost every few hours. Compared to other sites on the www it was ridiculously short, no matter how long you set timeout and cookieTimeout in core settings.
I looked into it more than twice in the last year coming up with almost nothing. After many hours of investigating I just postponed it again for times unknown.
It should be said that debugging the session/cookie based stuff - here Authentication - is quite a difficult past. Many things play into it making it hard to reproduce the issue.
The cake documentation also doesn't tell us, that for php sessions to work this long it is also required to raise the internal max_lifetime. I stumpled across this by accident. Always thought this would be taken care of by cake itself.
But after switching to database as session container I didn't notice any improvements either. So the server side garbage collector maybe wasn't responsible after all. At least not all alone.
So, to sum it up:
- Setting up timeouts was a waste of time
- Security level, as well (I just left it at `low`)
- Moving from php/cake to database didn't work either - although it provides little more control
- Raising the php.ini settings for gc_maxlifetime didn't work too well, either
I still get logged out after totally different lengths. Sometimes minutes, sometimes a few hours. It never lasts much longer.
Not only a deadly problem for a social network running with Cake.
I tried multiple times to add an encrypted cookie as `RememberMe` functionally (to quicklogin such a logged out user again). But I failed - as I later found out due to a PHP bug with srand/mt_srand and suhosin (details).
Thanks to miles' post regarding this bug I took a step forward and decided to take action (a lot of users have been complaining about unexplainable logouts the past months anyway).
AutoLogin? A way out?
I finally - after putting up with it for many years - adjusted Miles' great spadework with his AutoLogin component to work with my apps.
Basically, this component saves the user data to a cookie on login. As soon as the session gets lost again (for whatever reason!?) the component re-logins the user. It happens silently without bothering the user.
The code can be found here: github.com/dereuromark/cake-auto_login
I actually merged it into my Tools plugin. But for the sake of simplicity I left the forked rep from Miles intact and up-to-data.
Usage and Features
After successfully running it in a few cake2.x apps, I want to share the basic HOWTO.
The only required thing to do is adding the component globally in AppController:
{code type=php}
public $components = array('Session', 'RequestHandler', 'AutoLogin', 'Auth', ...);
{/code}
It is important to include it before any AuthComponent to avoid getting any "not logged in" error messages triggered by it.
You can use /Config/configs.php (or any other Configure place) to define its settings:
{code type=php}
$config['AutoLogin'] = array(
'controller' => 'account',
'username' => 'login',
'requirePrompt' => false
... //see the component for details on other options
);
{/code}
Please use the last one with caution. If `requirePrompt` is disabled you use AutoLogin for ALL logins. This requires users to always log out correctly in public places (especially in internet cafes this can be quite dangerous as others opening the site could hijack this logged in user even after several days). So make sure you use is only for sites where all users are properly informed and educated on this.
So for the default case you will need to add a checkbox into your login form:
{code type=php}
if (Configure::read('AutoLogin.active')) {
echo $this->Form->input('auto_login', array('type'=>'checkbox', 'label'=>__('Remember on this computer')));
}
{/code}
That's it.
You can easily test it using database sessions and truncating the session table after login.
It should log the user right back in as well as creating the new session table row. If everything is working right, the user shouldn't even notice that he wasn't logged in for a split second.
The if statement is optional. I use it to dynamically enable/disable the component based on the environment.
But if you use it, make sure you defined `active` as `true` in Configure.
Getting rid of the suhosin bug
As explained by Miles in the above links, most linux apache environments come with the suhosin patch which messes up srand by default. My localhost WAMP doesn't. So there it worked right away. But to get it to work on the linux environment, all there is to do is:
In your `/etc/php5/apache2/php.ini` add this line at the bottom:
{code type=php}
suhosin.srand.ignore = Off
{/code}
And don't forget to restart apache or at least `/etc/init.d/apache2 force-reload`.
TIP: I added a test case for this bug (see test file in the rep). Run it on every environment if you are not sure whether it is affected or not.
More tips
If you want to disable AutoLogin for specific sites you can simply set `active` to `false` for this site in your configs or dynamically in the controllers' constructor.
Remember: Since you need to include it before Auth etc you cannot dynamically add it to the list of components. But you can always disable the included component this way :)
The debug mode is on auto-detect by default. If you develop locally (debug > 0) you have it enabled right away. But, of course, you can overwrite this value in your configs.
Another important setting is `expires` - it defaults to `2 weeks` but can also easily be adjusted.
This has been an issue for me way too long.
I always hated the fact that users are logged out almost every few hours. Compared to other sites on the www it was ridiculously short, no matter how long you set timeout and cookieTimeout in core settings.
I looked into it more than twice in the last year coming up with almost nothing. After many hours of investigating I just postponed it again for times unknown.
It should be said that debugging the session/cookie based stuff – here Authentication – is quite a difficult past. Many things play into it making it hard to reproduce the issue.
The cake documentation also doesn’t tell us, that for php sessions to work this long it is also required to raise the internal max_lifetime. I stumpled across this by accident. Always thought this would be taken care of by cake itself.
But after switching to database as session container I didn’t notice any improvements either. So the server side garbage collector maybe wasn’t responsible after all. At least not all alone.
So, to sum it up:
- Setting up timeouts was a waste of time
- Security level, as well (I just left it at `low`)
- Moving from php/cake to database didn’t work either – although it provides little more control
- Raising the php.ini settings for gc_maxlifetime didn’t work too well, either
I still get logged out after totally different lengths. Sometimes minutes, sometimes a few hours. It never lasts much longer.
Not only a deadly problem for a social network running with Cake.
I tried multiple times to add an encrypted cookie as `RememberMe` functionally (to quicklogin such a logged out user again). But I failed – as I later found out due to a PHP bug with srand/mt_srand and suhosin (details).
Thanks to miles’ post regarding this bug I took a step forward and decided to take action (a lot of users have been complaining about unexplainable logouts the past months anyway).
AutoLogin? A way out?
I finally – after putting up with it for many years – adjusted Miles’ great spadework with his AutoLogin component to work with my apps.
Basically, this component saves the user data to a cookie on login. As soon as the session gets lost again (for whatever reason!?) the component re-logins the user. It happens silently without bothering the user.
The code can be found here: github.com/dereuromark/cake-auto_login
I actually merged it into my Tools plugin. But for the sake of simplicity I left the forked rep from Miles intact and up-to-data.
Usage and Features
After successfully running it in a few cake2.x apps, I want to share the basic HOWTO.
The only required thing to do is adding the component globally in AppController:
public $components = array('Session', 'RequestHandler', 'AutoLogin', 'Auth', ...);
It is important to include it before any AuthComponent to avoid getting any “not logged in” error messages triggered by it.
You can use /Config/configs.php (or any other Configure place) to define its settings:
$config['AutoLogin'] = array(
'controller' => 'account',
'username' => 'login',
'requirePrompt' => false
... //see the component for details on other options
);
Please use the last one with caution. If `requirePrompt` is disabled you use AutoLogin for ALL logins. This requires users to always log out correctly in public places (especially in internet cafes this can be quite dangerous as others opening the site could hijack this logged in user even after several days). So make sure you use is only for sites where all users are properly informed and educated on this.
So for the default case you will need to add a checkbox into your login form:
if (Configure::read('AutoLogin.active')) {
echo $this->Form->input('auto_login', array('type'=>'checkbox', 'label'=>__('Remember on this computer')));
}
That’s it.
You can easily test it using database sessions and truncating the session table after login.
It should log the user right back in as well as creating the new session table row. If everything is working right, the user shouldn’t even notice that he wasn’t logged in for a split second.
The if statement is optional. I use it to dynamically enable/disable the component based on the environment.
But if you use it, make sure you defined `active` as `true` in Configure.
Getting rid of the suhosin bug
As explained by Miles in the above links, most linux apache environments come with the suhosin patch which messes up srand by default. My localhost WAMP doesn’t. So there it worked right away. But to get it to work on the linux environment, all there is to do is:
In your `/etc/php5/apache2/php.ini` add this line at the bottom:
suhosin.srand.ignore = Off
And don’t forget to restart apache or at least `/etc/init.d/apache2 force-reload`.
TIP: I added a test case for this bug (see test file in the rep). Run it on every environment if you are not sure whether it is affected or not.
More tips
If you want to disable AutoLogin for specific sites you can simply set `active` to `false` for this site in your configs or dynamically in the controllers’ constructor.
Remember: Since you need to include it before Auth etc you cannot dynamically add it to the list of components. But you can always disable the included component this way
The debug mode is on auto-detect by default. If you develop locally (debug > 0) you have it enabled right away. But, of course, you can overwrite this value in your configs.
Another important setting is `expires` – it defaults to `2 weeks` but can also easily be adjusted.