Sessions don't work in Chrome but do in IE
By Pete Freitag
I observed an interesting thing today while helping a client. The problem was presented as:
We have a bunch of Chrome users having issues where a session variable is not working between page requests. We set the variable on one page, it is not defined on the next page request. If we tell them to try another browser, such as IE or Edge it works fine.
I have seen problems like this for many years and it doesn't often end up being a difference in the browser implementation, but rather the difference is that the user has essentially cleared their cookies when they try another browser. In this case the client confirmed that the problem went away when they use a new Incognito Chrome browser window.
Attacking the problem
Next I fired open Chrome developer tools to see what was happening. This particular website was serving requests over both http
(port 80) and https
(port 443). The session cookie (JSESSIONID
in this case) was getting the secure
flag set when the request came over https
, a request over http
would not get the secure
flag set.
When the secure
flag is set by a cookie the browser must not send that cookie over an insecure transport like plain http
. This is the essence of what a secure cookie does.
Eureka
Even though a request over http
would cause Tomcat or ColdFusion to set a new JSESSIONID
cookie, Chrome will not store that cookie if it already has a cookie with the same name and the secure flag is set.
So here is what happened:
- User requests https page, sets
JSESSIONID
with secure flag. - User makes request to non-secure http page, the JSESSIONID is not sent because it is a secure cookie. The server creates a new session, and tries to set a new JSESSIONID cookie, but the browser ignores this new cookie because it already has a JSESSIONID.
- User navigates to another page over non-secure http they do not have a session cookie to pass, repeat step 2.
Do all browsers work this way?
Both Chrome 71, and Firefox 64 prevent a secure cookie from being overwritten on plain http. I tested Edge 42 and it does not work the same way, it will overwrite the secure cookie with the non-secure cookie. Safari 12 works similar to Edge.
My assumption was that the browser would maintain separate cookie values for the secure origin and the non-secure origin in this case. My assumption was not correct on any modern browser. I tested a few old versions of Chrome and found that this implementation was added somewhere between Chrome 37 and Chrome 60 (I didn't want to test each version, I will leave that as an exercise for the reader ;-).
Here's an easy way to test a browser using httpbin.org a site/api for testing HTTP clients, it is useful because it serves requests over both plain http and https. Additionally their set cookie feature will set a cookie with a secure flag when requested over https:
- Set a secure cookie
test_secure=1
over https: https://httpbin.org/cookies/set/test_secure/1 - Next set a non-secure cookie
test_secure=2
over plain http: http://httpbin.org/cookies/set/test_secure/2
If you see test_secure=2 over http then the browser is overwriting the secure cookie, otherwise you will not see the test_secure cookie over http.
How do you work around this?
Fixing this is pretty straight forward, you have to redirect all http traffic to https and the problem is solved. There is not really any valid use cases for serving content on both http and https that I am aware of.
Sessions don't work in Chrome but do in IE was first published on February 06, 2019.
If you like reading about session, cookie, chrome, ie, or firefox then you might also like:
- One liner to download a Browser with PowerShell on Windows Server
- Cookie Expires / Max-Age 1969-12-31T23:59:59.000Z
- Firefox Aurora now Supports Content Security Policy 1.0
- J2EE Sessions in CF10 Uses Secure Cookies
Discuss / Follow me on Twitter ↯
Tweet Follow @pfreitagComments
Thank you for sharing your findings here. This solved the issue for me where I was getting "this set-cookie was blocked because it was not sent over a secure connection and would have overwritten a cookie with the Secure attribute." when trying to load cookie over http localhost, due to cookies were previously served over https localhost. Once I deleted cookies from https localhost, the cookies were loaded correctly over http localhost again.
Landed from https://stackoverflow.com/a/55478559/5490413.
Freddy from Ottawa, ON.