phpcakephphybridauth

CakePHP 3: Session was already started with Hybridauth 3


I have a LoginController where I do my usual login operation with combination of an email address and a password associated with the account.

I have separated my Hybridauth related code into a separate controller named OauthController where I have all my Hybridauth magic and where my callback / endpoint resides.

In the OauthController I check if user's email from the specified provider is already registered, and in either case I try to login that user with $this->Auth->setUser(object).

Whenever, or whatever from the $this->Auth is called, I get a response stating:

Session was already started

I have browser through CakePHP 3 code and found the following statement in:

vendor/cakephp/cakephp/src/Network/Session.php (335)

public function start()
{
    if ($this->_started) {
        return true;
    }

    if ($this->_isCLI) {
        $_SESSION = [];
        $this->id('cli');

        return $this->_started = true;
    }

    if (session_status() === \PHP_SESSION_ACTIVE) {
        throw new RuntimeException('Session was already started');
    }

    ...

And that's the point in code where that message is thrown at me.

Now, as I browsed through the Hybridauth code itself, I have found following in:

vendor/hybridauth/hybridauth/src/Storage/Session.php (46)

public function __construct()
{
    if (session_id()) {
        return;
    }

    if (headers_sent()) {
        throw new RuntimeException('HTTP headers already sent to browser and Hybridauth won\'t be able to start/resume PHP session. To resolve this, session_start() must be called before outputing any data.');
    }

    if (! session_start()) {
        throw new RuntimeException('PHP session failed to start.');
    }
}

And both of them call session_start, one before the other, although CakePHP's part is blocking me.

I have tried removing !session_start() check from Hybridauth, but then Hybridauth doesn't know where to read out it's thingies it needs to read.

So, as a demonstrator, I am trying to achieve this in OauthController:

<?php

namespace App\Controller;

use Hybridauth\Hybridauth;

class OauthController extends AppController
{

    public function callback($provider)
    {
        try {
            $hybridauth = new Hybridauth($config);

            // additional mystery code

            $hybridauth->authenticate();

            if($everything_okay) {
                $this->Auth->setUser($userObject); // and this is the point of failure
                return $this->redirect('/account'); // and this never happends... :(
            }
        }
    }

}

Any help, ideas, insights on how to deal with this are all welcome!


Solution

  • Simply start the CakePHP session manually before using the Hybridauth library, so that it bails out at the session_id() check and picks up the existing session.

    For example in your controller:

    $this->getRequest()->getSession()->start();
    
    // in CakePHP versions before 3.6/3.5
    // $this->request->session()->start();