Search code examples
phpfacebook-php-sdkcodeigniter-2

facebook sdk (php) can't get access token


EDITS: See this picture: http://trackauthoritymusic.com/wwwroot/images/fb-issue-bug.jpg.

  • For snapshots of the Network tab and all HTTPS headers from my page through FB's redirect.
  • The windows in the image above show the var_dump's in the code below:
    • For an access token I only get default the combined appId|secret.
    • When I var_dump $_REQUESTS at the first point of contact from Facebook, I get nothing so know codeigniter is not stripping the values, but i'm definitely not getting an "signed_request" post from Facebook!
  • I'm 85.1% sure my Facebook app settings are fine. I've made dozens of tweaks and resets while testing to no success.
  • And when I switch the settings to client-side approach with the access token in the browser hash, i DO get a valid token, but am desperately trying to avoid all that javascript on my page and will need the php integrated anyway.
  • All of this only happens once you've approved the app, and I can manually look up their membership in Insights, but know they can't access the app without seeing their token.

I had put this bug aside until now, since my ORIGINAL POST below April 24:....

It's been 3 days with trial-n-error and research:

My Environment: LAMP using facebook sdk 3 & CodeIgniter 2

Login Code:


    $CI->load->library('facebook', array("appId"=>APP_ID, "secret"=>APP_SECRET));
    $this->visitor['access_token'] = $CI->facebook->getAccessToken();            
    $fb_id = $CI->facebook->getUser();
    var_dump($CI->facebook); // see picture above
    var_dump($fb_id); // == 0
    if ($fb_id && $fb_id > 0) {
    $temp = $CI->users->getUserByFb($fb_id);
    if (!$temp) {
        $this->insertFBUser($fb_id);
        $this->visitor['redirect'] = "?prompt=newfb";
    } else {
        $this->visitor = array_merge($this->visitor, $temp);                   
        if (isset($this->visitor['user_allowed']) && $this->visitor['user_allowed'] == 0) {
            $CI->users->updateUser(array("user_allowed" => 1), $this->visitor['user_id']);
        }
    }
    } else {
    array_push($this->errors, $CI->input->get_post("error_msg", false));
    array_push($this->errors, $CI->input->get_post("error_code", false));
    array_push($this->errors, $CI->input->get_post("error_reason", false));
    array_push($this->errors, $CI->input->get_post("error", false));
    array_push($this->errors, $CI->input->get_post("error_description", false));    
    if ($CI->input->get_post("autoclose", false) == true) {
        array_push($this->errors, "javascript stackoverflow is encoding weird, but basically changes the hashtag of the pop-window, so the parent page automatically closes it");
    }
    var_dump($this->errors);
    die("nada");
    }

Research & Debugging:

  • This post describes my problem as well, but the solution did not work: stackoverflow.com/questions/8587098/suddenly-getuser-became-to-return-0-php-3-1-1-sdk with or without the trailing comma in the DROP_QUERY_PARAMS array on this page.

  • Facebook is sending me NO error messages in the url, post, or session and scraping my page fine

  • EVERYTHING worked fine a few days ago and i've changed very little around this code.

  • The login now fails whether i use http or https

  • The popup link opens at:
    www.facebook.com/dialog/oauth?client_id=222912307731474&redirect_uri=https%3A%2F%2Ftrackauthoritymusic.com%2Fmanage%2Fusers%2Flogin%3Fautoclose%3Dtrue&state=4522cb9da5bf5107d690a22eee6c5a2e&scope=email&display=popup while redirecting successfully to my desired login url with both state and code parameters apparently valid: trackauthoritymusic.com/manage/users/login?autoclose=true&state=4522cb9da5bf5107d690a22eee6c5a2e&code=AQBfSkI4y_VxhCuF3coVvNmjetdGZjugyFv0UsLlKt5sR5MEGdY8KqpDXZKvqHTGaSHhzY4pHXuR_zmilkwmoQ5y6M9jh15GPI6DXz5E2fSBizAVlrlebriNGcNZb4DRaDFK8cxPJoa9xB2ERuimtuizmlZERNa8hwJxLXtztqkWWhkLFCaGjQvAyyf5jJRkuoztmvfKDIZz3W9lslM6fk_m

but at this point, the sdk cannot get any access token or facebook session data.

PLEASE HELP!


Solution

  • I fixed this by using codeigniter's input library within the Facebook SDK to get the code/token and all $_GET/$_POST/$_REQUEST globals.

    See the git diff on the facebook sdk. I'm still not sure what i did to break thisthough. OAuth/Login WAS working consistently before a certain point. I'm sure this wasn't just some race condition on codeigniter occasionally clearing the globals

    @@ -490,10 +490,11 @@
    */
       public function getSignedRequest() {
         if (!$this->signedRequest) {
    -      if (!empty($_REQUEST['signed_request'])) {
    -        $this->signedRequest = $this->parseSignedRequest(
    -          $_REQUEST['signed_request']);
    -      } elseif (!empty($_COOKIE[$this->getSignedRequestCookieName()])) {
    +      $CI = & get_instance();
    +      $signed_request = $CI->input->get_post("signed_request");
    +      if (!empty($signed_request)) {
    +        $this->signedRequest = $this->parseSignedRequest($signed_request);
    +      } else if (!empty($_COOKIE[$this->getSignedRequestCookieName()])) {
             $this->signedRequest = $this->parseSignedRequest(
               $_COOKIE[$this->getSignedRequestCookieName()]);
           }
    @@ -691,15 +692,18 @@
       protected function getCode() {
    -    if (isset($_REQUEST['code'])) {
    -      if ($this->state !== null &&
    -          isset($_REQUEST['state']) &&
    -          $this->state === $_REQUEST['state']) {
    -
    +    $CI = & get_instance();
    +    $code = $CI->input->get_post("code");
    +    if (!empty($code)) {
    +      $state = $CI->input->get_post("state");
    +      if ($this->state !== null && $state && $this->state === $state) {
             // CSRF state has done its job, so clear it
             $this->state = null;
             $this->clearPersistentData('state');
    -        return $_REQUEST['code'];
    +        return $code;
           } else {
             self::errorLog('CSRF state token does not match one provided.');
             return false;
            $params['access_token'] = $this->getAccessToken();
         }