title: Facebook API - Required param "state" missing from persistent data
body: <p>I know that this question is a duplicate of another, however after searching Google and Stack Overflow, I have still yet to find a solution.</p>
  
  <p>I have some code which calls the Facebook API for a login URL.  However, I am doing it in a somewhat indirect way.  Basically here is the server flow:</p>
  
  <ol>
  <li>Client chooses to login to app with FB</li>
  <li>Client website (A) sends HTTP GET request to intermediate website (B)</li>
  <li>Website B returns login URL on website B which includes 2 callbacks: a login URL to FB generated with fb->getLoginUrl() and a callback to website A.</li>
  <li>Website A redirects to login page on Website B which redirects to login page on FB</li>
  <li>User logs in and grants permissions to app on FB website</li>
  <li>FB redirects to callback on website B which gets the access code.</li>
  <li>Website B redirects to Website A callback passing the access code as a $_GET variable</li>
  <li>Website A uses the access token as it wishes</li>
  </ol>
  
  <p>So very complicated and I only include the flow to possibly make answering this question and understanding the code in PHP easier. </p>
  
  <p>PHP
  Website A Code:</p>
  
  <pre><code>if (!isset($_GET['code'])) {
    $callback = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    $request_url = "http://embocorp.com/factory/api.php/facebook/login?callback=".$callback;
    header("Location: ".implode(json_decode(callAPI("GET", $request_url), true)['body']['data']));
  } else {
    echo $_GET['code'];
  }
  </code></pre>
  
  <p>Website B Code:
  api.php</p>
  
  <pre><code>if (!session_id()) {
    session_start();
  }
  
  require_once("vendor/autoload.php");
  
  $method = $_SERVER['REQUEST_METHOD'];
  $request = explode('/', trim($_SERVER['PATH_INFO'],'/'));
  $input = $_SERVER['PATH_INFO'];
  $table = array_shift($request);
  $key = array_shift($request);
  parse_str($_SERVER['QUERY_STRING'], $query_array);
  
  $callback = "http://embocorp.com/factory/api.php/facebook/callback?call=";
  
  function returnData($data, $options = "") {      
    $response = [
      "data"=&gt;$data
    ];
    return json_encode($response, $options);
  }
  function getFacebookConnection($appid, $appsecret) {
    return new Facebook\Facebook(['app_id' =&gt; $appid,'app_secret' =&gt; $appsecret,'default_graph_version' =&gt; 'v2.5',    'persistent_data_handler'=&gt;'session']);
  }
  function facebookHandleRequest($request, $connection, $details = null) {
    switch($request) {
      case "login":
        $callback_url = $GLOBALS["callback"].$GLOBALS['query_array']['callback'];
        echo returnData("http://embocorp.com/factory/login.php?fb=".getFacebookLoginURL($connection, $callback_url), JSON_UNESCAPED_SLASHES);
        break;
      case "callback":
        if (!empty($GLOBALS["query_array"])) {
          foreach ($_COOKIE as $k=&gt;$v) {
            if(strpos($k, "FBRLH_")!==FALSE) {
              $_SESSION[$k]=$v;
            }
          }
          $access = getFacebookAccessCode($connection);
          $called = $GLOBALS['query_array']['called'];
          header("location: ".$called."?code=".$access);
        } else {
          echo returnError(400, "Bad Request, missing authorization");
        }
        break;
      case "me":
        if (!empty($GLOBALS["query_array"]) &amp;&amp;  array_key_exists("accessToken", $GLOBALS["query_array"]) == true) {
          $response = $connection-&gt;sendRequest('GET', '/me', [], $GLOBALS["query_array"]["accessToken"], 'eTag', 'v2.2');
          $user = $response-&gt;getGraphUser();
          echo returnData($user);
        } else {
          echo returnError(400, "Bad Request, missing authorization");
        }
        break;
      default:
        echo returnError(404, "Request URI Not Found");
        break;
    }
  }
  function getFacebookLoginURL($connection, $callback_url) {
    $helper = $connection-&gt;getRedirectLoginHelper();
    $permissions = ['manage_pages', 'publish_pages', 'read_insights'];
    $loginUrl = $helper-&gt;getLoginUrl($callback_url, $permissions);
    foreach ($_SESSION as $k=&gt;$v) {                    
      if(strpos($k, "FBRLH_")!==FALSE) {
        if(setcookie($k, $v)) {
          $_COOKIE[$k]=$v;
        }
      }
    }
    return $loginUrl;
  }
  function getFacebookAccessCode($fb){
    if (!session_id()) {
      $accessToken = $_SESSION['facebook_access_token'];
      return $accessToken;
    } else {
      $helper = $fb-&gt;getRedirectLoginHelper();
      try {
        $accessToken = $helper-&gt;getAccessToken();
      } catch(Facebook\Exceptions\FacebookResponseException $e) {
        echo 'Graph returned an error: ' . $e-&gt;getMessage();
        exit;
      } catch(Facebook\Exceptions\FacebookSDKException $e) {
        echo 'Facebook SDK returned an error: ' . $e-&gt;getMessage();
        exit;
      }
      if (isset($accessToken)) {
        $_SESSION['facebook_access_token'] = (string) $accessToken;
        return (string) $accessToken;
      } else {
        return false;
      }
    }
  } 
  
  switch ($table) {
    case "facebook":
      $fb = getFacebookConnection($appid, $appsecret);
      facebookHandleRequest($key, $fb);
      break;
    case "twitter":
      echo "no";
      break;
    default:
      exit();
      break;
  }
  
  session_write_close();
  
  ?&gt;
  </code></pre>
  
  <p>login.php</p>
  
  <pre><code>if (!session_id()) {
    session_start();
  }
  if (isset($_GET['fb'])) {
    $redirect = str_replace("fb=", "", $_SERVER['QUERY_STRING']);
    header("Location: ".$redirect);
  } else {
    echo "ni";
  }
  </code></pre>
  
  <p>Again, thank you for any help, this has been driving me crazy for 72 hours now.  </p>