View Issue Details

IDProjectCategoryView StatusLast Update
0007212OXID eShop (all versions)4.02. Session handlingpublic2021-03-03 13:53
Reporterpvanhemmen 
PrioritynormalSeveritymajorReproducibilityalways
Status acknowledgedResolutionopen 
Product Version6.2.2 
Target VersionFixed in Version 
Summary0007212: session_start() in EE Config breaks session handling when force_sid GET param is present
DescriptionIn the _getShopIdFromSession() method in oxideshop-ee/Core/Config.php the session is started when the force_sid param is present before start() ist called in oxideshop-ce/source/Core/Session.php. This way the forced sid is never written to the session cookie because te check for isSessionStarted() in line 242 of the start() method always returns true and the request never reaches the point where the id is stored in the cookie.

This way logged in users will be logged out with any subsequent requests. A consistent behaviour to keep users logged in accross different domains (for example when using different TLDs for different languages) is crucial though.
Steps To ReproduceOn a multi-language multi-domain EE Setup try to switch to another language TLD in the user account and then navigate to any other page in the acount. This will log the current user out.
Additional InformationI think session handling should not take place in Config classes, especially not starting and stopping sessions.
TagsEE
ThemeNot defined
BrowserNot defined
PHP Version7.1
Database VersionMySQL 5.7

Activities

QA

2021-02-23 10:57

administrator   ~0013382

Last edited: 2021-02-23 11:02

View 3 revisions

Hi pvanhemmen,

After setting up an environment with different hostnames for languages and even a subshop I couldn't reproduce the described issue. I switched the languages, deleted the cookies, switched the shop id, and stayed within the account area. but I was never logged out.
So I digged into the code :

The methods getShopId and initializeShop are executed in this order:

1.  \OxidEsales\EshopCommunity\Core\Config::getShopId
1.1 \OxidEsales\EshopEnterprise\Core\Config::calculateActiveShopId
2.  \OxidEsales\EshopEnterprise\Core\Config::initializeShop


So, you are right. When calculating the current active shop id, the code
if ($sid) {
    if (session_status() === PHP_SESSION_NONE) {
        session_id($sid);
        session_start();
        // Remove pragma header after session start as it might affect system caching.
        header_remove('Pragma');
    }
}


is executed before the session is started "officially" and OxidEsales\Eshop\Core\Session->start() wasn't called yet.

1.
Config.php:68, OxidEsales\Eshop\Core\Config->calculateActiveShopId()
Config.php:814, OxidEsales\Eshop\Core\Config->getShopId()
Config.php:437, OxidEsales\Eshop\Core\Config->init()
ShopControl.php:590, OxidEsales\Eshop\Core\ShopControl->_runOnce()
ShopControl.php:136, OxidEsales\Eshop\Core\ShopControl->start()
Oxid.php:27, OxidEsales\EshopCommunity\Core\Oxid::run()
index.php:16, {main}()


2.
Session.php:271, OxidEsales\Eshop\Core\Session->start()
Config.php:472, OxidEsales\Eshop\Core\Config->initializeShop()
Config.php:563, OxidEsales\Eshop\Core\Config->initializeShop()
Config.php:440, OxidEsales\Eshop\Core\Config->init()
ShopControl.php:590, OxidEsales\Eshop\Core\ShopControl->_runOnce()
ShopControl.php:136, OxidEsales\Eshop\Core\ShopControl->start()
Oxid.php:27, OxidEsales\EshopCommunity\Core\Oxid::run()
index.php:16, {main}()


While debugging I noticed that the if query fails everytime, when the session was restored by the parameter "force_sid". That's the reason I couldn't reproduce the issue:
if ($this->isSessionStarted() === false && $this->_allowSessionStart()) {
See \OxidEsales\EshopCommunity\Core\Session::start

The logic works as expected, because the method \OxidEsales\EshopCommunity\Core\Session::isSessionStarted checks if the session was already started:
public function isSessionStarted()
{
    return session_status() === PHP_SESSION_ACTIVE;
}

This behaviour makes totally sense as the framework must expected that something from the "outside" has started a session already. Furthermore the method description states: "This check needed for ERP functionality", which fits the just made expectation.

But besides that I will address the topic, to move the session logic to the Session class as I think you are right with that.

Greetings,
Michael

pvanhemmen

2021-02-25 11:51

reporter   ~0013385

Hey Michael,

thanx for your detailed and thorough response. I may not have been clear in my explanations, but what I meant is that the user is logged out with any *subsequent* request after switching languages. I was able to reproduce this problem on a completely fresh standard EE installation. To reproduce, have a setup like the one above with at least to different languages and two different domains and then:

1.) Clear all sessions and cookies on all domains
2.) Login with your user in language 1
3.) Navigate to the user account. Any page will do, I asume the dashboard here
4.) Switch to language 2. This will work, because the force_sid param is written to the session, but - and this is important - it is not stored in a cookie due to the bug described above.
5.) Navigate to any other page in the account, for example the "Change Password" page. The user now isn't considerd logged in and redirected to the login page - thus effectively logged out.

I hope this helps!

All the best,
Paul

pvanhemmen

2021-02-25 11:52

reporter  

session_bug_cropped.gif (1,548,632 bytes)

pvanhemmen

2021-02-25 11:52

reporter   ~0013386

P.S.: I have attached an animated GIF of the issue.

QA

2021-03-03 13:52

administrator   ~0013389

Last edited: 2021-03-03 13:53

View 2 revisions

Hi Paul!

I finally could reproduce it, thank you for providing the further information and the gif.

How I reproduced it:

1. Open the file /etc/hosts and add those two lines:
127.0.0.1       shopde
127.0.0.1       shopen
2. Goto the administration area and edit the language 0.
3. Write the domain "shopde" into the field "Base URL".
4. Do the same for language 1, except use the domain "shopen".

I recommend a new browser session (incognito mode) for the following steps.

5. Goto the frontend and deleted all of your cookies. Make sure you aren't logged in afterwards.
6. Do the very same steps, which are documented in the gif session_bug_cropped.gif from pvanhemmen or the comment https://bugs.oxid-esales.com/view.php?id=7212#c13385.


Thank you for reporting that!
Greetings
Michael