Task: Fix Auth / login problems caused by conflicting cookies.
Referring to bug: https://sourceforge.net/tracker/index.php?func=detail&aid=1166376&group_id=7130&atid=107130
and numerous forum posts.
Numerous users have complained that they can't login. This problem usually arises, when G2 is accessed with different urls.
- when accessed as standalone and as embedded
- when accessed as www.domain.com/... and as domain.com
Example: embedded/standalone G2
- cookie from embedded: path = /
- cookie from standalone: path = /gallery2/
1. user logs out in embedded -> cookie with path = / is for an anonymous G2 session
2. user visits G2. browser sends cookie for path = / and for path = /gallery2/. Somehow, cookie with path = / has precedence.
3. G2 sends html, user is not logged in.
4. User tries to login, G2 sends cookie to browser: cookie with path = /gallery2/ is now for a logged in session.
5. User requests next G2 view, browser sends again both cookies, somehow the one with path = / has precedence.
7. G2 checks the session from the path = / cookie and resumes the anonymous session.
-> G2 will always set the path = /gallery2/ cookie but read the path = / cookie -> can't login unless cookie with path = / is deleted on client browser.
Example 2: www.domain.com/g2/, domain.com/g2/
Same issue, but now with domains instead of paths. G2 sets the www.domain.com cookie, and receives the .domain.com cookie.
It's not possible that G2 always updates the cookie it received, because the browser doesn't send the the cookie path/domain in its cookie-header which it sends to the server.
RFC 2109 and 2965 describe the cookie management. 2965 is newer and makes 2109 obsolete.
From the RFCs:
About which cookies the user agent (or browser) should send back to the server:
If multiple cookies satisfy the criteria above, they are ordered in
the Cookie header such that those with more specific Path attributes
precede those with less specific. Ordering with respect to other
attributes (e.g., Domain) is unspecified.
So, G2 should receive multiple GALLERYSID cookies when multiple are present on the browser matching the path or a substring of the path.
An example from the RFC:
4.2 Example 2
This example illustrates the effect of the Path attribute. All
detail of request and response headers has been omitted. Assume the
user agent has no stored cookies.
Imagine the user agent has received, in response to earlier requests,
the response headers
Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1";
A subsequent request by the user agent to the (same) server for URLs
of the form /acme/ammo/... would include the following request
Note that the NAME=VALUE pair for the cookie with the more specific
Path attribute, /acme/ammo, comes before the one with the less
specific Path attribute, /acme. Further note that the same cookie
name appears more than once.
I tested this. There are a number of options to retrieve cookie data in php. $_COOKIE is indexed by NAME, so you get only a single GALLERYSID cookie. $_GLOBALS['HTTP_SERVER_VARS'] lists all GALLERYSID cookies! But no paths for the cookies
Same for $_GLOBALS['_SERVER'] = $_SERVER.
So, why don't we get the path for each component? The RFC defines that the browser sends the path to the server. If we received the path, we could choose the more specific path / update the right cookie.
I checked the packets sent from FF and IE, both don't send the path, they just send a single Attribut Cookie: NAME=VALUE; NAME=VALUE; ... list.
G2 (GallerySession.class::init) doesn't check $_SERVER['HTTP_COOKIE'], so it only receives/checks one GALLERYSID cookie per request.
Proposed fix A:
Set Path = '/' and domain = '.domain.com' independent of the full path and the subdomain. I saw this in phpbb, it should work.
That way G2 will never have different cookies for the same install, even if accessed in different ways.
Problem of the proposed fix:
What if multiple G2 are running on the same domain? Probably in different paths or subdomains. No problem as long no user visits no more than a single of these G2 installs.
But here's the real solution:
cookie (domain, path and) name should be configurable. If they are not set /overriden by the admin, the defaults will be used (.domain.com, /, GALLERYSID) and this will be the best solution for 90% of all users. Those who need multiple G2 on a single server, can define another cookie name for all different G2 installations.
These values if set, should be defined in config.php to not require a DB lookup for this query as the session is used too often and too early.
The cookie name could also be GALLERYSID . rand(0,1000) set on install time. That way, the probability that two G2 on the same domain would have to solve a cookie conflict by changing the cookie name manually would be reduced.
Proposed fix B:
Instead of checking $_COOKIE, we could check $_SERVER['HTTP_COOKIE']. The RFC defines that the more specific cookies should be listed first. $_COOKIE lists only the one GALLERYSID cookie that is listed as the last of all cookies with the name = GALLERYSID in this list.
G2 should choose the first cookie with name = GALLERYSID in the list $_SERVER['HTTP_COOKIE'], because it's path is more specific, i.e. it will always be the one G2 tries to overwrite / G2 sends back.
This would fix the standalone/embedded G2 auth/login problems.
But this probably doesn't solve the subdomain.domain.com/domain.com auth/login problem. From the RFC:
Ordering with respect to other
attributes (e.g., Domain) is unspecified.
It would be interesting what the practice is.
I'd prefer Fix B, because it's easier / less admin options. But if it doesn't solve the sub.domain.com problem, then we have to go with Fix A.