Session - SSO :: Upgrade framework from 4.11.15 to higher loosing session state

Silverstripe Version: 4.11.15 to higher

Question: Upgrading from silvestripe framework 4.11.15 to higher is making to loose session state

Hi,

Currently one of the site I am managing is running on Silverstripe framework 4.11.15. We have SSO configured via OpenID. All is working fine with this version.
Once we upgrade Silverstripe framework from 4.11.15 to anything higher the session state is not working ie after SSO session is loosing the state.

We have custom implementation of Session class. A wrapper to already existing Control\Session.php class.

Once we upgrade the framework, the user is redirected in a loop. Upon troubleshooting what we found was the sate of the session is not getting saved. When we downgrade everything works fine with no issues.

I have been through the Session documentation and have added cookie_samesite=‘Strict’.

Posting a question here in the forum if anyone else had similar experience and if I am missing something after the upgrade that I need to do for sessions to work.

Really appreciate any help here please.

Common Session class in one of our common modules used across three sites.

class Session
{

    private static $inst = null;

    private $session = null;

    public function __construct()
    {
        if (Controller::curr()) {
            $request = Controller::curr()->getRequest();
            $this->session = $request->getSession();
        }
    }

    public function startSession()
    {
        $request = Injector::inst()->get(HTTPRequest::class);
        return $this->session ? $this->session->start($request) : false;
    }

    public function getValue($name)
    {
        return $this->session ? $this->session->get($name) : null;
    }

    public function setValue($name, $value)
    {
        return $this->session ? $this->session->set($name, $value) : null;
    }

    public function getAllValues()
    {
        return $this->session ? $this->session->getAll() : [];
    }

    public function clearValue($name)
    {
        return $this->session ? $this->session->clear($name) : false;
    }

    public function clearAllValues()
    {
        return $this->session ? $this->session->clearAll() : false;
    }

    public function saveSession()
    {
        $request = Injector::inst()->get(HTTPRequest::class);
        return $this->session ? $this->session->save($request) : false;
    }

    public function destroySession()
    {
        return $this->session ? $this->session->destroy(true) : false;
    }

    public static function init()
    {
        if (!isset(self::$inst)) {
            self::$inst = new Session();
        }
        return self::$inst;
    }

    public static function start()
    {
        return self::init()->startSession();
    }

    public static function get($name)
    {
        return self::init()->getValue($name);
    }

    public static function set($name, $value)
    {
        return self::init()->setValue($name, $value);
    }

    public static function get_all()
    {
        return self::init()->getAllValues();
    }

    public static function clear($name)
    {
        return self::init()->clearValue($name);
    }

    public static function clear_all()
    {
        return self::init()->clearAllValues();
    }

    public static function save()
    {
        return self::init()->saveSession();
    }

    public static function destroy()
    {
        return self::init()->destroySession();
    }

}

There’s nothing obvious here that stands out - though it’s not clear why your wrapper exists, it seems like you’ve just made static versions of the methods which ultimately just call the relevant instance methods on the current session. What problem is this solving for you that the current API doesn’t?

Things that might help you debug to discover what’s going wrong, and additional info that might help us give more specific guidance:

  • Does the session get saved when you don’t use your wrapper?
  • Does this happen for you in any updated projects which don’t use OpenID SSO?
  • Is the OpenID SSO implementation you’re using open source? It might be that there’s some incompatability there rather than in this wrapper or core code.
  • What specifically led you to the conclusion that the session isn’t being saved?
  • Were there any errors in your logs or the browser’s dev console?
  • You mentioned setting cookie_samesite=‘Strict’ - I assume this was after it already wasn’t working? Did it have any effect at all? Note that that’s an optional thing that you do not need to do for things to work, the default value of “Lax” is equivalent to the old behaviour of not having a samesite value explicitly defined.
  • Have you stepped through with a debugger? Is it possible that at the time you instantiate your wrapper you don’t have a session set in the controller?
    Note that you should be able to get the current HTTPRequest from the injector - Director::handleRequest() registers it as a service, so you don’t necessarily need Controller::curr(). Which, by the way, I think will throw an exception if there’s no current controller. You should probably have Controller::has_curr() in that conditional statement instead.

Hi Guy,

thanks for looking into this ticket. The wrapper was done before my time but looking at the picture this is what I can tell you. There are few modules that are getting shared between three sites. One of them is a common module that has this Session implementation. Other is the Customized OpenID SSO module. Within the SSO module there are references to Session::save and few other Session static calls. Scaterred on the three sites there is usage of Session::save etc…So instead of going to all these places to fix a wrapper was created to address the issue.

to answer your other questions

  1. Will check and get back.
  2. All the sites have SSO so haven’t tested
  3. Yes it is Open Source. Looking at the code we are using https://github.com/jumbojett/OpenID-Connect-PHP/blob/v0.5.0/src/OpenIDConnectClient.php
  4. I have added Debug statements that indicate that. With working version the state is always the same but with non-working version upon authentication it keeps changing. Have not done xdebug but will install now and follow the flow.

Have tested another method. After upgrading the framework, I have copied “SilverStripe\Control\Session.php” from 4.11.15’s version to non working Session.php file. Removed Session setting like cookie_samesite=‘strict’ from YAML. With this setup the auth works with no issues.

So that tells me that there is something with ‘SilverStripe\Control\Session.php’ that is making the site go in infinite redirect loop.

I compared both 4.11.15 version of ‘SilverStripe\Control\Session.php’ and 4.12 and the differences seams to be around cookie_samesite and how cookie is getting saved. Attached is the file that shows the differences.https://drive.google.com/file/d/1jpQfrke8RFvHF81Ixg9XpocCkjGsGxwA/view?usp=sharing

I am still debugging, Will post if I find anything. Thanks for the help.

Cheers
R

Hmm. Have you tried upgrading to 4.12 (or higher) without setting cookie_samesite=‘strict’? This sounds a lot like the OpenID needs to share your session cookie, and you’re telling it not to by setting samesite to strict.

Yes have tried that. Actually that was the first version I tried i.e without setting ‘cookie_samesite’. Am going to be doing more troubleshooting today.