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.
Related
I found a strange cookie problem on safari. If you surf to http://2much.ch you can enter with FF/IE and surf inside the site.
But if you use safari, you can enter only once; you can't surf inside the site. I found that Safari doesn't set the entered cookie, but FF/IE does.
What is wrong here?
It looks like you hit a Safari bug here; you are redirecting any visiting browser to /entry while setting the cookie at the same time, and Safari is ignoring the Set-Cookie header when encountering the 302 HTTP status:
$ curl -so /dev/null -D - http://4much.schnickschnack.info/
HTTP/1.1 302 Moved Temporarily
Server: nginx/0.7.61
Date: Sun, 19 Jul 2009 12:20:49 GMT
Content-Type: text/html;charset=utf-8
Connection: keep-alive
Content-Length: 14260
Content-Language: de
Expires: Sat, 1 Jan 2000 00:00:00 GMT
Location: http://4much.schnickschnack.info/entry
Set-Cookie: colorstyle="bright"; Path=/; Expires=1248092449.12
Set-Cookie: _ZopeId="73230900A39w5NG7q4g"; Path=/
Technically, this would be a bug in Apple's Foundation Classes, I've found a WebKit bug that states this is the case.
I suppose the workaround is to set the cookie not in index_html but in entry instead.
In the intervening years since I first answered this question, this issue now appears solved, at least it was for Safari 6 when someone tested all major browsers for Set-Cookie support on 302 redirects in 2012.
A month ago, I ran into this issue. At first I thought it was a corrupted cookie jar as I could clean out the cookies and go.
However, it popped up again. This time I spent an hour going through it, watching what was sent, reviewing what safari sent back, and I found the problem.
In this case, I had an array of cookie values being sent to the browser after login prior to the redirect. The values looked something like 'user id', 'user full name', 'some other id', etc.
( yes, the id's are encrypted so no worries there )
My user full name was actually in a <lastname>, <firstname> format.
When safari was posting the cookie back to the server, everything after the comma after the lastname was dropped. It was only posting back values up to that point.
When i removed the comma the rest of the values started working just fine.
So it appears that if you send a cookie value that contains a comma, then safari doesn't properly escape that in it's internal storage. Which leads me to think that if they aren't properly escaping commas, then there are probably some security issues with safari's cookie handling code.
Incidentally, this was tested on Win 7 x64 with safari 4.0.5. Also I put up a web page at: http://cookietest.livelyconsulting.com/ which shows this exact problem.(I removed that test site)
IE, FF, and chrome all correctly set the cookie. safari does not.
Looks like this is no longer an issue. See http://blog.dubbelboer.com/2012/11/25/302-cookie.html
We've run into a very similar issue where Safari (v. 7.0.6) would ignore a cookie. The cookie header looked perfectly fine, almost identical to another cookie which was remembered.
It turned out that the culprit was the previous cookie header having a malformed expires value. Safari's handling of broken cookie headers is evidently not as robust as that of the other browsers.
I ran into same issue with Chrome. Chrome doesn't ignore the set-cookie header while you are redirecting, but you never know the order (set cookie first or redirect first). Here is something I have tried:
I have a website, which supports English and French. I implemented it (with php) this way:
localhost has a link to localhost/fr (which set-cookie to French and redirect to localhost). It works. (set cookie first)
localhost/path1 has a link to localhost/fr?return=/path1 (which set-cookie to French and redirect to localhost/path1). It doesn't work. (redirect first, the language didn't change)
localhost/path1 has a link to localhost/fr?return=www.google.com (which set-cookie to French and redirect to google). When I came back to my website again, it's in French. (which means set-cookie to French is not ignored, only executed after redirect)
Hope I make myself clear, English is a foreign language to me.
After a great deal of pain, I found out that Safari (15.3) actually does save and my cookie, but it never displayed in developer tools storage -> cookies, but it works fine.
Here's the cookie I create and return in a Netlify function.
const secureCookie = cookie.serialize('jwtToken', JSON.stringify(jwtToken), {
secure: process.env.CONTEXT !== 'dev',
domain: process.env.CONTEXT === 'dev' ? 'localhost' : '.domain.com',
httpOnly: true,
sameSite: true,
expires: new Date(Date.now() + (1000 * jwtToken.expires_in))
})
and netlify function return
return {
statusCode: 200,
headers: {
"Cache-Control": "no-cache",
},
multiValueHeaders: {
"Set-Cookie": [secureCookie],
},
body: JSON.stringify(body),
}
I followed this tutorial (https://learn.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-2.1) to implement ResponseCache on my controller-action.
In short, I added
services.AddResponseCaching(); and app.UseResponseCaching(); in the startup and this tag [ResponseCache( Duration = 30)] on my controller.
Then I added a <h2>#DateTime.Now</h2> in my view and what I expected.... was the same datetime.now for 30 seconds.
But it doesn't, it just shows the new time on every reload (F5).
I made sure my devtools in chrome do not say 'disable cache'.
It's both with and without the chrome devtools open, on my local machine, now trying on a brandnew .net core mvc project.
One thing I noticed (with devtools open) is that the request has this header: Cache-Control: max-age=0. Does this influence the behaviour?
I thought it would mean something because it looks like the request says 'no cache' but that strikes me as weird because I didn't put the header in and I would say the default behaviour of chrome wouldn't be to ignore caches?
A header like Cache-Control: max-age=0 effectively disables all caching. Resources are basically expired as soon as they come off the wire, so they are always fetched. This header originates from the server. The client has nothing to do with it.
Assuming you haven't disabled response caching manually in some way by accident. Then, the most likeliest situation is that you're doing something where the response caching middleware will never cache. The documentation lists the following conditions that must be satisfied before responses will be cached, regardless of what you do:
The request must result in a server response with a 200 (OK) status code.
The request method must be GET or HEAD.
Terminal middleware, such as Static File Middleware, must not process the response prior to the Response Caching Middleware.
The Authorization header must not be present.
Cache-Control header parameters must be valid, and the response must be marked public and not marked private.
The Pragma: no-cache header must not be present if the Cache-Control header isn't present, as the Cache-Control header overrides the Pragma header when present.
The Set-Cookie header must not be present.
Vary header parameters must be valid and not equal to *.
The Content-Length header value (if set) must match the size of the response body.
The IHttpSendFileFeature isn't used.
The response must not be stale as specified by the Expires header and the max-age and s-maxage cache directives.
Response buffering must be successful, and the size of the response must be smaller than the configured or default SizeLimit.
The response must be cacheable according to the RFC 7234 specifications. For example, the no-store directive must not exist in request or response header fields. See Section 3: Storing Responses in Caches of RFC 7234 for details.
However, in such situations, the server should be sending Cache-Control: no-cache, not max-age=0. As a result, I'm leaning towards some misconfiguration somewhere, where you have set this max age value and either forgot or overlooked it.
This is working for me in a 3.1 app to not let F5/Ctrl+F5 or Developer Tools in Firefox or Chrome bypass server cache for a full response.
In startup add this little middleware before UseResponseCaching().
// Middleware that fixes server caching on F5/Reload
app.Use(async (context, next) =>
{
const string cc = "Cache-Control";
if (context.Request.Headers.ContainsKey(cc))
{
context.Request.Headers.Remove(cc);
}
const string pragma = "Pragma";
if (context.Request.Headers.ContainsKey(pragma))
{
context.Request.Headers.Remove(pragma);
}
await next();
});
app.UseResponseCaching();
Haven't noticed any problems...
I use bottle set/get cookie mecanism to track my user_id (with 'secret' param when calling set/get_cookie()
During normal http(s) request everything is fine but when making a xhr request (same domain)user_id = request.get_cookie('user_id', secret='mysecret') returns None.
When checking on client browser, cookie and key/value are still available.
How to deal with it ?
(I've always been told that xhr requests are http requests, so from same domain, cookies should be shared, no ? is problem arrising from Bottle 'secret' handling ?)
The documentation states, when setting a cookie the default path is "/"
https://bottlepy.org/docs/dev/tutorial.html#tutorial-cookies
path: Limit the cookie to a given path (default: /)
But the code comment says default is "current path" e.g. /XXX/dev
https://github.com/bottlepy/bottle/blob/master/bottle.py#L1796
:param path: limits the cookie to a given path (default: current path)
Based on this behaviour we can assume the later is true.
So when setting the cookie, if you want any path to have access to the cookie from your domain. Set the path in your cookie as "/"
set_cookies('test', 123, secret='mysecret', path='/')
I tried to set_cookies('test', 123, secret='mysecret') under AJAX request, it worked, but still couldn't find previous cookies.
Then I remarked that my previous cookies, called cook1 and cook2, written under 'normal' http request, if they had same domain, had different 'path' (under Chrome ressource explorer). They were set under path '/XXX/dev' and my AJAX request was just under path '/XXX'
So I modified my AJAX request from /XXX/do_stuff to point to '/XXX/dev/do_stuff', and then, surprise ! cook1 and cook2 could be read by my AJAX request.
Not sure if it's a Bottle bug or if such behaviour is designed on purpose (in this case, if someone can explain to me why...), but at least I have my solution.
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.
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.