]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Facebook bridge mostly working again with new OAuth 2.0 flow
authorZach Copley <zach@status.net>
Mon, 26 Sep 2011 05:32:19 +0000 (05:32 +0000)
committerZach Copley <zach@status.net>
Mon, 26 Sep 2011 05:32:19 +0000 (05:32 +0000)
plugins/FacebookBridge/FacebookBridgePlugin.php
plugins/FacebookBridge/actions/facebookfinishlogin.php
plugins/FacebookBridge/actions/facebooklogin.php
plugins/FacebookBridge/lib/facebookclient.php

index 62ae3813311fea419c2b2efdf1a3408c2c198a7e..9d83c9f474f88e1653d87de5c696ac540f382c08 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
+ * Copyright (C) 2010-2011, StatusNet, Inc.
  *
  * A plugin for integrating Facebook with StatusNet. Includes single-sign-on
  * and publishing notices to Facebook using Facebook's Graph API.
@@ -21,7 +21,7 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
- * @category  Pugin
+ * @category  Plugin
  * @package   StatusNet
  * @author    Zach Copley <zach@status.net>
  * @copyright 2011 StatusNet, Inc.
@@ -41,7 +41,7 @@ define("FACEBOOK_SERVICE", 2);
  * @category  Plugin
  * @package   StatusNet
  * @author    Zach Copley <zach@status.net>
- * @copyright 2010 StatusNet, Inc.
+ * @copyright 2010-2011 StatusNet, Inc.
  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
  * @link      http://status.net/
  */
@@ -108,6 +108,7 @@ class FacebookBridgePlugin extends Plugin
         switch ($cls)
         {
         case 'Facebook': // Facebook PHP SDK
+            include_once $dir . '/extlib/base_facebook.php';
             include_once $dir . '/extlib/facebook.php';
             return false;
         case 'FacebookloginAction':
@@ -351,26 +352,26 @@ class FacebookBridgePlugin extends Plugin
             $action->script('https://connect.facebook.net/en_US/all.js');
 
             $script = <<<ENDOFSCRIPT
-FB.init({appId: %1\$s, session: %2\$s, status: true, cookie: true, xfbml: true});
+FB.init({appId: %1\$s, status: true, cookie: true, xfbml: true, oauth: true});
 
 $('#facebook_button').bind('click', function(event) {
 
     event.preventDefault();
 
     FB.login(function(response) {
-        if (response.session && response.perms) {
-            window.location.href = '%3\$s';
+        if (response.authResponse) {
+            window.location.href = '%2\$s';
         } else {
             // NOP (user cancelled login)
         }
-    }, {perms:'read_stream,publish_stream,offline_access,user_status,user_location,user_website,email'});
+    }, {scope:'read_stream,publish_stream,offline_access,user_status,user_location,user_website,email'});
 });
 ENDOFSCRIPT;
 
             $action->inlineScript(
-                sprintf($script,
+                sprintf(
+                    $script,
                     json_encode($this->facebook->getAppId()),
-                    json_encode($this->facebook->getSession()),
                     common_local_url('facebookfinishlogin')
                 )
             );
@@ -385,18 +386,16 @@ ENDOFSCRIPT;
     function onEndLogout($action)
     {
         if ($this->hasApplication()) {
-            $session = $this->facebook->getSession();
+            //$session = $this->facebook->getSession();
             $fbuser  = null;
             $fbuid   = null;
 
-            if ($session) {
                 try {
                     $fbuid  = $this->facebook->getUser();
                     $fbuser = $this->facebook->api('/me');
                  } catch (FacebookApiException $e) {
                      common_log(LOG_ERROR, $e, __FILE__);
                  }
-            }
 
             if (!empty($fbuser)) {
 
index 3d2fb571d7aa0280535063212683ed73a6fcb333..d58944e83df53cb66feaa008d623447e88a7ed77 100644 (file)
@@ -22,7 +22,7 @@
  * @category  Plugin
  * @package   StatusNet
  * @author    Zach Copley <zach@status.net>
- * @copyright 2010 StatusNet, Inc.
+ * @copyright 2010-2011 StatusNet, Inc.
  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  * @link      http://status.net/
  */
@@ -33,39 +33,43 @@ if (!defined('STATUSNET')) {
 
 class FacebookfinishloginAction extends Action
 {
-    private $facebook = null; // Facebook client
-    private $fbuid    = null; // Facebook user ID
-    private $fbuser   = null; // Facebook user object (JSON)
+    private $fbuid       = null; // Facebook user ID
+    private $fbuser      = null; // Facebook user object (JSON)
+    private $accessToken = null; // Access token provided by Facebook JS API
 
     function prepare($args) {
         parent::prepare($args);
 
-        $this->facebook = new Facebook(
-            array(
-                'appId'  => common_config('facebook', 'appid'),
-                'secret' => common_config('facebook', 'secret'),
-                'cookie' => true,
-            )
+        // Check cookie for a valid access_token
+
+        $cookie = $this->get_facebook_cookie(
+            common_config('facebook', 'appid'),
+            common_config('facebook', 'secret')
         );
 
-        // Check for a Facebook user session
+        $this->accessToken = $cookie['access_token'];
 
-        $session = $this->facebook->getSession();
-        $me      = null;
+        common_debug("cookie = " . var_export($cookie, true));
 
-        if ($session) {
-            try {
-                $this->fbuid  = $this->facebook->getUser();
-                $this->fbuser = $this->facebook->api('/me');
-            } catch (FacebookApiException $e) {
-                common_log(LOG_ERROR, $e, __FILE__);
-            }
-        }
+        $this->fbuser = json_decode(
+            file_get_contents(
+                'https://graph.facebook.com/me?access_token='
+                . $this->accessToken
+            )
+        );
 
         if (!empty($this->fbuser)) {
+
+            $this->fbuid  = $this->fbuser->id;
+            common_debug("fbuser = " . var_export($this->fbuser, true));
+            common_debug("fbuid = " . $this->fbuid);
+
             // OKAY, all is well... proceed to register
 
             common_debug("Found a valid Facebook user.", __FILE__);
+
+            return true;
+
         } else {
 
             // This shouldn't happen in the regular course of things
@@ -88,43 +92,44 @@ class FacebookfinishloginAction extends Action
             );
         }
 
-        return true;
+        return false;
     }
 
-    function handle($args)
-    {
-        parent::handle($args);
+    function get_facebook_cookie($app_id, $app_secret) {
+        $args = array();
 
-        if (common_is_real_login()) {
+        parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);
+
+        ksort($args);
+        $payload = '';
 
-            // User is already logged in, are her accounts already linked?
+        foreach ($args as $key => $value) {
+            if ($key != 'sig') {
+               $payload .= $key . '=' . $value;
+            }
+        }
 
-            $flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
+        if (md5($payload . $app_secret) != $args['sig']) {
+            return null;
+        }
 
-            if (!empty($flink)) {
+        return $args;
+    }
 
-                // User already has a linked Facebook account and shouldn't be here!
+    function handle($args)
+    {
+        parent::handle($args);
 
-                common_debug(
-                    sprintf(
-                        'There\'s already a local user %d linked with Facebook user %s.',
-                        $flink->user_id,
-                        $this->fbuid
-                    )
-                );
+        if (common_is_real_login()) {
 
-                $this->clientError(
-                    // TRANS: Client error displayed when trying to connect to a Facebook account that is already linked
-                    // TRANS: in the same StatusNet site.
-                    _m('There is already a local account linked with that Facebook account.')
-                );
+            // This will throw a client exception if the user already
+            // has some sort of foreign_link to Facebook.
 
-            } else {
+            $this->checkForExistingLink();
 
-                // Possibly reconnect an existing account
+            // Possibly reconnect an existing account
 
-                $this->connectUser();
-            }
+            $this->connectUser();
 
         } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
             $this->handlePost();
@@ -133,6 +138,58 @@ class FacebookfinishloginAction extends Action
         }
     }
 
+    function checkForExistingLink() {
+
+        // User is already logged in, are her accounts already linked?
+
+        $flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
+
+        if (!empty($flink)) {
+
+            // User already has a linked Facebook account and shouldn't be here!
+
+            common_debug(
+                sprintf(
+                    'There\'s already a local user %d linked with Facebook user %s.',
+                    $flink->user_id,
+                    $this->fbuid
+                )
+            );
+
+            $this->clientError(
+                // TRANS: Client error displayed when trying to connect to a Facebook account that is already linked
+                // TRANS: in the same StatusNet site.
+                _m('There is already a local account linked with that Facebook account.')
+            );
+
+            return;
+       }
+
+       $cur = common_current_user();
+       $flink = Foreign_link::getByUserID($cur->id, FACEBOOK_SERVICE);
+
+       if (!empty($flink)) {
+
+            // There's already a local user linked to this Facebook account.
+
+            common_debug(
+                sprintf(
+                    'There\'s already a local user %d linked with Facebook user %s.',
+                    $cur->id,
+                    $this->fbuid
+                )
+            );
+
+            $this->clientError(
+                // TRANS: Client error displayed when trying to connect to a Facebook account that is already linked
+                // TRANS: in the same StatusNet site.
+                _m('There is already a local account linked with that Facebook account.')
+            );
+
+            return;
+        }
+    }
+
     function handlePost()
     {
         $token = $this->trimmed('token');
@@ -365,19 +422,19 @@ class FacebookfinishloginAction extends Action
         }
 
         $args = array(
-            'nickname'        => $nickname,
-            'fullname'        => $this->fbuser['first_name']
-                . ' ' . $this->fbuser['last_name'],
-            'homepage'        => $this->fbuser['website'],
-            'bio'             => $this->fbuser['about'],
-            'location'        => $this->fbuser['location']['name']
+            'nickname' => $nickname,
+            'fullname' => $this->fbuser->name,
+            'homepage' => $this->fbuser->website,
+            'location' => $this->fbuser->location->name
         );
 
         // It's possible that the email address is already in our
         // DB. It's a unique key, so we need to check
-        if ($this->isNewEmail($this->fbuser['email'])) {
-            $args['email']           = $this->fbuser['email'];
-            $args['email_confirmed'] = true;
+        if ($this->isNewEmail($this->fbuser->email)) {
+            $args['email']           = $this->fbuser->email;
+            if (isset($this->fuser->verified) && $this->fuser->verified == true) {
+                $args['email_confirmed'] = true;
+            }
         }
 
         if (!empty($invite)) {
@@ -407,7 +464,7 @@ class FacebookfinishloginAction extends Action
                 'Registered new user %s (%d) from Facebook user %s, (fbuid %d)',
                 $user->nickname,
                 $user->id,
-                $this->fbuser['name'],
+                $this->fbuser->name,
                 $this->fbuid
             ),
             __FILE__
@@ -474,7 +531,7 @@ class FacebookfinishloginAction extends Action
                                 . '%s (fbuid %d), filename = %s',
                              $user->nickname,
                              $user->id,
-                             $this->fbuser['name'],
+                             $this->fbuser->name,
                              $this->fbuid,
                              $filename
                         ),
@@ -537,7 +594,7 @@ class FacebookfinishloginAction extends Action
         common_debug(
             sprintf(
                 'Connected Facebook user %s (fbuid %d) to local user %s (%d)',
-                $this->fbuser['name'],
+                $this->fbuser->name,
                 $this->fbuid,
                 $user->nickname,
                 $user->id
@@ -616,7 +673,7 @@ class FacebookfinishloginAction extends Action
         $flink->service = FACEBOOK_SERVICE;
 
         // Pull the access token from the Facebook cookies
-        $flink->credentials = $this->facebook->getAccessToken();
+        $flink->credentials = $this->accessToken;
 
         $flink->created = common_sql_now();
 
@@ -627,8 +684,8 @@ class FacebookfinishloginAction extends Action
 
     function bestNewNickname()
     {
-        if (!empty($this->fbuser['name'])) {
-            $nickname = $this->nicknamize($this->fbuser['name']);
+        if (!empty($this->fbuser->username)) {
+            $nickname = $this->nicknamize($this->fbuser->username);
             if ($this->isNewNickname($nickname)) {
                 return $nickname;
             }
@@ -636,8 +693,7 @@ class FacebookfinishloginAction extends Action
 
         // Try the full name
 
-        $fullname = trim($this->fbuser['first_name'] .
-            ' ' . $this->fbuser['last_name']);
+        $fullname = $this->fbuser->name;
 
         if (!empty($fullname)) {
             $fullname = $this->nicknamize($fullname);
@@ -694,10 +750,8 @@ class FacebookfinishloginAction extends Action
          $result = User::staticGet('email', $email);
 
          if (empty($result)) {
-             common_debug("XXXXXXXXXXXXXXXXXX We've never seen this email before!!!");
              return true;
          }
-         common_debug("XXXXXXXXXXXXXXXXXX dupe email address!!!!");
 
          return false;
      }
index fa3cc7a6f2a27f8fc7f201a016b6bfbe66cc427c..afb30a2b1f969dba6c79f25317569d316485feab 100644 (file)
@@ -72,17 +72,16 @@ class FacebookloginAction extends Action
 
         $facebook = Facebookclient::getFacebook();
 
+        $params = array(
+          'scope' => 'read_stream,publish_stream,offline_access,user_status,user_location,user_website,email',
+          'redirect_uri' => common_local_url('facebookfinishlogin')
+        );
+
         // Degrade to plain link if JavaScript is not available
         $this->elementStart(
             'a',
             array(
-                'href' => $facebook->getLoginUrl(
-                    array(
-                        'next'       => common_local_url('facebookfinishlogin'),
-                        'cancel'     => common_local_url('facebooklogin'),
-                        'req_perms'  => 'read_stream,publish_stream,offline_access,user_status,user_location,user_website,email'
-                    )
-                 ),
+                'href' => $facebook->getLoginUrl($params),
                 'id'    => 'facebook_button'
             )
         );
index 0469ce8aca2aa7d98c9cebc8e2d8135a09630ed7..768950ffa25817d5adf004d26abd327a813d427f 100644 (file)
@@ -916,7 +916,7 @@ class Facebookclient
     static function addFacebookUser($fbuser)
     {
         // remove any existing, possibly outdated, record
-        $luser = Foreign_user::getForeignUser($fbuser['id'], FACEBOOK_SERVICE);
+        $luser = Foreign_user::getForeignUser($fbuser->id, FACEBOOK_SERVICE);
 
         if (!empty($luser)) {
 
@@ -937,9 +937,9 @@ class Facebookclient
 
         $fuser = new Foreign_user();
 
-        $fuser->nickname = $fbuser['name'];
-        $fuser->uri      = $fbuser['link'];
-        $fuser->id       = $fbuser['id'];
+        $fuser->nickname = $fbuser->username;
+        $fuser->uri      = $fbuser->url;
+        $fuser->id       = $fbuser->id;
         $fuser->service  = FACEBOOK_SERVICE;
         $fuser->created  = common_sql_now();
 
@@ -950,8 +950,8 @@ class Facebookclient
                 LOG_WARNING,
                     sprintf(
                         'Failed to add new Facebook user: %s, fbuid %d',
-                        $fbuser['name'],
-                        $fbuser['id']
+                        $fbuser->username,
+                        $fbuser->id
                     ),
                     __FILE__
             );
@@ -962,8 +962,8 @@ class Facebookclient
                 LOG_INFO,
                 sprintf(
                     'Added new Facebook user: %s, fbuid %d',
-                    $fbuser['name'],
-                    $fbuser['id']
+                    $fbuser->name,
+                    $fbuser->id
                 ),
                 __FILE__
             );