3

The whole scenario is that I have added facebook login extension in my opencart store , everything works fine when a new user clicks login with facebook add email and password and clicks login then comes a confirm login dialog which has two buttons "cancel" and "login" if user clicks login it takes the user to my store but when user clicks "cancel" it should take the user back to the login page at my store but instead it gives the error "Fatal error : uncaught exception with a message serialization of closure is not allowed
which is for this line "$_SESSION["HA::STORE"][$key] = serialize($value); I am using the following function which contains this line :

public function set( $key, $value)
    {
        $key = strtolower( $key );

        $_SESSION["HA::STORE"][$key] = serialize($value);
    }

I have tried this var_dump(serialize($value)); and it returns a string How can I serialize this? I have searched for it but not find any helpful solution

UPDATE :

function login()
    {
        Hybrid_Logger::info( "Enter Hybrid_Provider_Adapter::login( {$this->id} ) " );

        if( ! $this->adapter ){
            throw new Exception( "Hybrid_Provider_Adapter::login() should not directly used." );
        }

        // clear all unneeded params
        foreach( Hybrid_Auth::$config["providers"] as $idpid => $params ){
            Hybrid_Auth::storage()->delete( "hauth_session.{$idpid}.hauth_return_to"    );
            Hybrid_Auth::storage()->delete( "hauth_session.{$idpid}.hauth_endpoint"     );
            Hybrid_Auth::storage()->delete( "hauth_session.{$idpid}.id_provider_params" );
        }

        // make a fresh start
        $this->logout();

        # get hybridauth base url
        $HYBRID_AUTH_URL_BASE = Hybrid_Auth::$config["base_url"];

        # we make use of session_id() as storage hash to identify the current user
        # using session_regenerate_id() will be a problem, but ..
        $this->params["hauth_token"] = session_id();

        # set request timestamp
        $this->params["hauth_time"]  = time();

        # for default HybridAuth endpoint url hauth_login_start_url
        #   auth.start  required  the IDp ID
        #   auth.time   optional  login request timestamp
        $this->params["login_start"] = $HYBRID_AUTH_URL_BASE . ( strpos( $HYBRID_AUTH_URL_BASE, '?' ) ? '&' : '?' ) . "hauth.start={$this->id}&hauth.time={$this->params["hauth_time"]}";

        # for default HybridAuth endpoint url hauth_login_done_url
        #   auth.done   required  the IDp ID
        $this->params["login_done"]  = $HYBRID_AUTH_URL_BASE . ( strpos( $HYBRID_AUTH_URL_BASE, '?' ) ? '&' : '?' ) . "hauth.done={$this->id}";

        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_return_to"    , $this->params["hauth_return_to"] );
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_endpoint"     , $this->params["login_done"] ); 
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.id_provider_params" , $this->params );

        // store config to be used by the end point 
        Hybrid_Auth::storage()->config( "CONFIG", Hybrid_Auth::$config );

        // move on
        Hybrid_Logger::debug( "Hybrid_Provider_Adapter::login( {$this->id} ), redirect the user to login_start URL." );

        Hybrid_Auth::redirect( $this->params["login_start"] );
    }

In the function_login , set() is called by this :

Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_return_to"    , $this->params["hauth_return_to"] );
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_endpoint"     , $this->params["login_done"] ); 
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.id_provider_params" , $this->params );
Haroon
  • 496
  • 5
  • 14
  • 31
  • 1
    The problem is in the caller of `set()`, it's not passing a proper argument. I suspect you forgot to put `()` after a function name to call the function, so it's trying to store the function itself in the session. – Barmar Oct 06 '16 at 00:18
  • 1
    Show the code that calls `set()`. – Barmar Oct 06 '16 at 00:18
  • @Barmar I have updated the question , please have a look – Haroon Oct 06 '16 at 00:25
  • 1
    If you're storing something in `$_SESSION` you don't need to manually serialize it, that happens in the session handler code already. Just do `$_SESSION["HA::STORE"][$key] = $value;` – Sammitch Oct 06 '16 at 00:56
  • when i use $_SESSION["HA::STORE"][$key] = $value; it redirect back to the same page this variable $value contains the address when user clicks on cancel button – Haroon Oct 06 '16 at 01:01
  • I have elaborated my question – Haroon Oct 06 '16 at 01:13

1 Answers1

2

I'm guessing you are passing or getting passed a closure as the $value parameter of set().

You need to either check for and ignore closures using reflection

public function set( $key, $value)
{
    if (is_object($value)) {
        try {
            $reflection = new ReflectionFunction($value);
            if ($reflection->isClosure()) {
                //Trigger a E_USER_NOTICE if you want to avoid silently failing
                trigger_error("You cannot pass a closure as the second parameter of set()");
                return; // Do nothing else
            }
        } catch (\ReflectionException $e) {
            // Catch the exception thrown if $value is not a closure
        }
    }
    $key = strtolower( $key );

    $_SESSION["HA::STORE"][$key] = serialize($value);
}

Or you can catch and ignore the exception:

function set( $key, $value)
{
    $key = strtolower( $key );
    try{
        $_SESSION["HA::STORE"][$key] = serialize($value);
    } catch (\Exception $e) {
        // Catch the exception thrown and handle it however you want
    }
}

Or look at this github project for serializing closures

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Omn
  • 2,982
  • 1
  • 26
  • 39
  • var_dump(serialize($value)); this return a string . I don't understand how $value is a closure then? – Haroon Oct 06 '16 at 00:12
  • 1
    @mehar444 You have not provided enough context for me to explain. Running `var_dump(serialize($value));` when `$value` is a closure will result in an Exception being thrown as described here: http://stackoverflow.com/questions/13734224/exception-serialization-of-closure-is-not-allowed – Omn Oct 06 '16 at 00:17
  • after trying your code it gives me this : Warning: ReflectionFunction::__construct() expects parameter 1 to be string, array given in /var/www/html/mdpocketClipboards.com/catalog/model/social_login_free/hybrid/storage.php on line 63 – Haroon Oct 06 '16 at 00:19
  • actually i am using facebook api – Haroon Oct 06 '16 at 00:20
  • I was getting error when user clicks cancel on facebook login dialog. – Haroon Oct 06 '16 at 00:21
  • @mehar444 If you change the !is_string() to is_object() you will no longer get that warning. I have edited the answer with this change. – Omn Oct 06 '16 at 00:25
  • @mehar444 looking at the additional code you provided, it seems like `Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.id_provider_params" , $this->params );` is probably what is triggering the issue. `$this->params` is an array and probably contains a closure somewhere which is what is causing the issue. – Omn Oct 06 '16 at 00:33
  • How can I check that sir? – Haroon Oct 06 '16 at 00:36
  • @mehar444 You can wrap that line in a try catch statement or iterate over the array and try serializing each element. You have all the tools you need to solve this, the rest you will have to figure out for yourself. – Omn Oct 06 '16 at 00:44