Short Question:
Why doesn't my session cookie's expiry time get updated in the browser when my session's expirty time is updated on the server?
Long Question:
I posted a similar question about this a few weeks ago but I didn't have all of the facts at the time. I now have more detail and the nature of the question has changed so I'm posting it as a new question.
First of all, in CakePHP 2, I've set up APP/Config/core.php with the following for the session:
Configure::write('Session', array(
'defaults' => 'database',
'cookie' => 'mycookie',
'timeout' => 1 // 1 minute - just for testing
));
So, I load a page which in my app which creates the session in the database. All good so far.
The session is stamped to expire at 1341288066 which is equal to Tue, 03 Jul 2012 04:01:06 GMT. Again, this is great because that's 1 minute from now. Exactly what I wanted.
If I look in Firefox's cookie screen, I find the cookie just as I would have expected it:
Name: mycookie
Content: aqm0gkmjfsuqje019at8cgsrv3
Host: localhost
Path: /
Send for: Any type of connection
Expires: Tue 03 Jul 2012 11:01:06 AM ICT // (04:01:06 GMT)
Now, within this 1-minute window, I go back to my app and refresh the page. Then, I check the session to see if it's updated. It shows 1341288122 against the session id aqm0gkmjfsuqje019at8cgsrv3 which is equal to Tue, 03 Jul 2012 04:02:02 GMT which, again, is what I expected. The expiry of the session has been updated to be 1 minute from when I last reloaded the page.
Unfortunately, the cookie in the browser is still set to Expires: Tue 03 Jul 2012 11:01:06 AM ICT (ie: 04:01:06 GMT) and that's exactly what it does, meaning that the next time I press refresh, Cake generates a brand new session ID even though the old one is still technically valid.
My question is basically what is going on here? Why doesn't the cookie get updated with the new expiry date in the browser?
The issue you have spotted is indeed unexpected and ends sessions where they should stay alive.
This is the result of how CakePHP uses the Session functions of PHP. There is an entry (#3047) in the CakePHP bugtracker, where Mark Story (CakePHP developer) agrees this should be fixed
I can agree that the cookies should be updated alongside the session times stored in the session. However, that's not how PHP's internal features for session handling work. There seem to be a few different ways to workaround this issue.
As this will change the current behavior (however weird it may be), the fix is postponed to version 2.3, though.
I think managing the cookie state outside of PHP is going to be the most appropriate solution. I don't know how safe of a change this is for existing applications though. Changing how sessions works can be dramatic change and allowing users to stay logge din much longer might not be what all developers are expecting.
This appears to be how PHP handles sessions. PHP does not update the cookie on each request (see: http://php.net/manual/en/function.session-set-cookie-params.php#100672). Instead of relying on the expiry time in this cookie, CakePHP compares the current time with the actual session timeout in Session::_validAgentAndTime().
The problem can be solved by using the two parameters in combination.
Configure::write('Session', array(
'cookie' => 'CAKEPHP',
'defaults' => 'php',
'timeout' => 60, // 60 minutes: Actual Session Timeout
'cookieTimeout' => 1440, // 1440 minutes: 24 hrs: Actual Cookie Timeout
'autoRegenerate' => true,
'requestCountdown' => 1,
'checkAgent' => false,
));
autoRegenerate: generates Session Cookie after refresh. The refresh count after which the Session Cookie should be regenerated is determined by the next parameter.
requestCountdown: keep the value of this parameter as low as possible. This is the number of refresh/reload after which the Session Cookie will regenerated.
Related
I'm losing my mind here - I'm looking into an issue where some signout functionality in an application I have isn't working because the authentication cookie is not being cleared. The thing is that our "signout" endpoint does include the appropriate set-cookie header in the response - here's what I get looking at the raw response in Firefox:
set-cookie: Auth.myapp=; domain=app.mydomain.com; expires=Thu, 26-Nov-2020 13:19:20 GMT; path=/; secure; HttpOnly
Firefox is reporting this error in the console:
Cookie “Auth.myapp” has been rejected because it is already expired
This is kind of confusing, not only have I successfully used set-cookie with a past-date in expires before, it's even codified in RFC6265 as the accepted way to request a client remove a cookie:
Finally, to remove a cookie, the server returns a Set-Cookie header
with an expiration date in the past. The server will be successful
in removing the cookie only if the Path and the Domain attribute in
the Set-Cookie header match the values used when the cookie was
created.
So I need to set an expires date in the past to clear the cookie ... but doing so causes the browser to reject it? Does anyone know what's going on here?
To be clear I have checked that the cookie name, path, secure and SameSite match (update: I suspected that because I hadn't explicitly specified a SameSite this might be the cause, but after making sure the cookie is both set and cleared with SameSite=None it is still not working).
As far as I can tell, the message is harmless - the cookies are indeed deleted based on my testing. And Googling the message leads to this changeset, which indicates that the deletion does happen, just with additional logging.
// If the new cookie has expired -- i.e. the intent was simply to delete
// the old cookie -- then we're done.
if (aCookie->Expiry() <= currentTime) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader,
"previously stored cookie was deleted");
+ CookieLogging::LogMessageToConsole(
+ aCRC, aHostURI, nsIScriptError::warningFlag,
+ CONSOLE_REJECTION_CATEGORY, "CookieRejectedExpired"_ns,
+ AutoTArray<nsString, 1>{
+ NS_ConvertUTF8toUTF16(aCookie->Name()),
+ });
NotifyChanged(oldCookie, u"deleted", oldCookieIsSession);
return;
The message seems unnecessary however, and there is a bug report about it.
This occurs when using a null , false, or empty string in the cookie value.
It is only flagged as a warning in Firefox.
Other browsers do not show this warning.
I'm having a similar problem today with the same error message as the OP.
This happened in the past and my solution then was, rather than setting a time in the past, I set the value to nothing (as a failsafe) and also set 'expires' to 'time() + 1' (so a future time with the cookie expiring almost instantly).
setcookie('cookiename','',[
'expires' => time() + 1,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'secure' => true,
'samesite' => 'strict'
]);
Unfortunately, this workaround seems to suddenly be failing today and that failure does seem to be unique to Firefox. (So, yup, perhaps an FF bug?)
Chrome and Vivaldi are still working fine with it. I didn't test on Safari nor Edge as yet.
I'm on Laravel 5.7 and trying to get it so that my session expires and logs me out after 2 minutes.
In my session.php file i did:
'lifetime' => 2,
'expire_on_close' => false,
I will then leave my computer for example like 15 minutes, come back, refresh, and I'm still logged in?
Can you tell me why and how to fix it. Many thanks.
Ok I've figured it out.
The reason is I'm using Auth::logoutOtherDevices in Login function, and this function automatically generates the remember me cookie.
Thank you guys so much.
update .env file
SESSION_LIFETIME=2
From the docs the lifetime looks like it is in seconds so the lifetime would be
SESSION_LIFETIME=120 and not 2.
Edit: Please could you try set the option:
'expire_on_close' => true,
This will force the session to expire on browse close.
I found a potential answer to your issue here: Laravel - Auth Session not expiring after browser close
It sounds like it could be a chrome problem.
Try your solution on firefox to see if it is a chrome issue.
Have a read of that thread i linked.
Please make sure to check with your configurations.
In Session.php set lifetime to your desired time for session expiration.
Also in upgraded versions of laravel session lifetime is not set hard anymore, instead it takes from .env file.
You can try below configurations.
In your config/session.php
'lifetime' => env('SESSION_LIFETIME', 2),
And set below key in your .env file
SESSION_LIFETIME=2
due to the fact that my users have configured their sessions to reopen each time they reopen their firefox browser. the 'session' cookies come back.
but my website needs fresh authentication if the session cookie is not present or 24 hours old. so I am having this problem of needing to manually remove the expired cookies each time i reopen browser after 24 hours.
to combat this, i tired to put a 'Logout' link on my page which should have helped me. but unfortunately it is not helping...
i tried below code to remove the cookies, but it seems it does not remove the cookies from the sqilte table in which firefox stores its cookies. After the following code is run, cookies reappear.. (or are they not getting removed???) how can i achieve that?
code:
function Delete_Cookie( name, path, domain )
{
document.cookie=name+"="+((path) ? ";path="+path:"")+((domain)?";domain="+domain:"")+";expires=Thu, 01 Jan 1970 00:00:01 GMT";
}
$("#Logout").click(function() {
Delete_Cookie('SecOne','/','.mydomain.com');
Delete_Cookie('SecTwo','/','.mydomain.com');
alert("Bye");
});
Although I can't say for certain what the problem is, there are a few possibilities:
The domain name could be wrong.
You could write a test delete line that doesn't use the path and domain names and see if it works then. If the cookies get deleted after that change, then it's the string you made for the delete line, or the parameters that are passed in that are wrong.
Also, perhaps it is possible another section of your code is causing the cookies to reappear. Check to see if there's any other cookie setting things that get called after this is.
Or maybe the page needs reloaded in order for the cookies to disappear
If the cookie is HttpOnly cookie, it is not able to read/delete from HTTPS secured webpage. If the cookie is normal one, below functionality can be used for delete cookie.
function deleteCookie(keyName){
var allcookies = document.cookie, i, cookiearray = null, name = null;
cookiearray = allcookies.split(';');
for (i = 0; i < cookiearray.length; i++) {
name = cookiearray[i].split('=')[0].trim();
if (name === keyName) {
document.cookie = name + '=000;expires=Thu, 1 Jan 1970 00:00:00 UTC; path=/';
}
}
}
Note: Session cookies are not able to delete even browser is getting closed. This is known bug in chrome browsers. Refer below link
Cookie issue in chrome
I know this is an old thread but I was having the same problem as I kept trying to set a cookie with a time in the past, thinking it would expire and not show in FF cookie manager.
Setting the cookie to expire in the future but having a blank value got rid of it. Not sure why.
setcookie(mycookie,"", time()+5000,'/');
Using FireFox v40.0.3
Seems there have been a few bugs logged with Firefox and it's handling of cookie expiration.
I recently switched over to Cake2.0, and was having some issues with Sessions timing out much sooner than they should.
Copying the example from the documentation, I set the session type to php, and set the timeout to 3 days (4320 mins). However, after reading various articles, it seems that even after setting the timeout to 3 days in Cake, PHP may destroy the session in GC if PHP.ini is set with a shorter timeout for the session or GC.
So, I changed the Session default to cake, with the same timeout.
Configure::write('Session', array(
'defaults' => 'cake',
'timeout' => 4320,
));
Configure::write('Security.level', 'medium');
However, while this should leave me logged in for 3 days, I find I barely get 3 hours before I need to log in again.
Is there an issue with Session timeouts that I should be aware of, or is the timeout in seconds (not minutes?) or is it being influenced by the Security.level like in 1.3? I haven't been able to find any hard documentation about how this works in 2.0, or what could be causing the issues.
Thanks in advance.
Answer:
For anyone coming in later and seeing this. There is a bug in 2.0.5 where the Session timeout was not saving the value in Config.write();
To solve, update to 2.0.6 (or 2.1 when it leaves beta)
If you are using the security component, you can always try changing the expiration on them to 3 hours as well:
$components = array(
'Security' => array(
'csrfExpires' => '+3 hour'
)
);
I am not saying this is a good idea to do, but it could help you narrow down the problem. If you are using the Security component, this is probably the issue.
Also, the Session.timeout is in minutes (not seconds).
I need to keep Security.level set on medium for Ajax reason.
But I want that If the user close browser his session will destroy.
How can I do that?
Thanks in advance!
Config/core.php
Configure::write('Session', array(
'defaults' => 'php',
'cookieTimeout' => 0, //Lives until the browser is closed.
'checkAgent' => false //To fix a little the Chrome Frame problem
));
Unless you're persisting session data (ie: storing session data in a cookie with an expiration date in the future), then the session should be destroyed when the user closes the browser.
Unfortunately I'm not familiar with the CakePHP framework so I cannot comment on its API. However, if you want to explicitly end a session you can do so in PHP with session_destroy().
Hope that helps.
You could remove the session cookie with JS when the page is closed (remember: page close is also triggered when the user just navigates away - maybe just to the next page of yours).
i guess you could fire on ajax command on page unload to call session_destroy()
http://book.cakephp.org/view/1317/destroy for CakePHP - but yes, CakePHP does set a proper session cookie which is deleted by the browser when it closes.
What you really are probably concerned about is session hijacking - and so you really want some kind of a logout on site closure. You can't do this - the best alternative method that I know of is:
A short session timeout with an "Are you there?" AJAX refresh - the timeout can be controlled independently of the security level now using Configure::write('Session.timeout', $seconds);, where for medium security level the timeout seconds are multiplied by 100. Banks use this method.