]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - lib/apiauth.php
Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing
[quix0rs-gnu-social.git] / lib / apiauth.php
index d7f8017eb1e0bc99161112b9999cd51c2793647e..37070d212fc5c6f40e309e2a3393a934fcd79295 100644 (file)
  *
  * @category  API
  * @package   StatusNet
+ * @author    Adrian Lang <mail@adrianlang.de>
+ * @author    Brenda Wallace <shiny@cpan.org>
+ * @author    Craig Andrews <candrews@integralblue.com>
+ * @author    Dan Moore <dan@moore.cx>
+ * @author    Evan Prodromou <evan@status.net>
+ * @author    mEDI <medi@milaro.net>
+ * @author    Sarven Capadisli <csarven@status.net>
  * @author    Zach Copley <zach@status.net>
  * @copyright 2009 StatusNet, Inc.
  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
@@ -31,7 +38,8 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR.'/lib/api.php';
+require_once INSTALLDIR . '/lib/api.php';
+require_once INSTALLDIR . '/lib/apioauth.php';
 
 /**
  * Actions extending this class will require auth
@@ -45,8 +53,135 @@ require_once INSTALLDIR.'/lib/api.php';
 
 class ApiAuthAction extends ApiAction
 {
+    var $access_token;
+    var $oauth_access_type;
+    var $oauth_source;
 
-    var $auth_user = null;
+    /**
+     * Take arguments for running, and output basic auth header if needed
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        if ($this->requiresAuth()) {
+
+            $this->consumer_key = $this->arg('oauth_consumer_key');
+            $this->access_token = $this->arg('oauth_token');
+
+            if (!empty($this->access_token)) {
+                $this->checkOAuthRequest();
+            } else {
+                $this->checkBasicAuthUser();
+                // By default, all basic auth users have read and write access
+
+                $this->access = self::READ_WRITE;
+            }
+        }
+
+        return true;
+    }
+
+    function handle($args)
+    {
+        parent::handle($args);
+    }
+
+    function checkOAuthRequest()
+    {
+        common_debug("We have an OAuth request.");
+
+        $datastore   = new ApiStatusNetOAuthDataStore();
+        $server      = new OAuthServer($datastore);
+        $hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
+
+        $server->add_signature_method($hmac_method);
+
+        ApiOauthAction::cleanRequest();
+
+        try {
+
+            $req  = OAuthRequest::from_request();
+            $server->verify_request($req);
+
+            $app = Oauth_application::getByConsumerKey($this->consumer_key);
+
+            if (empty($app)) {
+
+                // this should really not happen
+                common_log(LOG_WARN,
+                           "Couldn't find the OAuth app for consumer key: $this->consumer_key");
+
+                throw new OAuthException('No application for that consumer key.');
+            }
+
+            // set the source attr
+
+            $this->oauth_source = $app->name;
+
+            $appUser = Oauth_application_user::staticGet('token',
+                                                         $this->access_token);
+
+            // XXX: check that app->id and appUser->application_id and consumer all
+            // match?
+
+            if (!empty($appUser)) {
+
+                // read or read-write
+                $this->oauth_access_type = $appUser->access_type;
+
+                // If access_type == 0 we have either a request token
+                // or a bad / revoked access token
+
+                if ($this->oauth_access_type != 0) {
+
+                    // Set the read or read-write access for the api call
+                    $this->access = ($appUser->access_type & Oauth_application::$writeAccess)
+                      ? self::READ_WRITE : self::READ_ONLY;
+
+                    if (Event::handle('StartSetApiUser', array(&$user))) {
+                        $this->auth_user = User::staticGet('id', $appUser->profile_id);
+                        Event::handle('EndSetApiUser', array($user));
+                    }
+
+                    $msg = "API OAuth authentication for user '%s' (id: %d) on behalf of " .
+                      "application '%s' (id: %d).";
+
+                    common_log(LOG_INFO, sprintf($msg,
+                                                 $this->auth_user->nickname,
+                                                 $this->auth_user->id,
+                                                 $app->name,
+                                                 $app->id));
+                    return true;
+                } else {
+                    throw new OAuthException('Bad access token.');
+                }
+            } else {
+
+                // also should not happen
+                throw new OAuthException('No user for that token.');
+        }
+
+        } catch (OAuthException $e) {
+            common_log(LOG_WARN, 'API OAuthException - ' . $e->getMessage());
+            common_debug(var_export($req, true));
+            $this->showOAuthError($e->getMessage());
+            exit();
+        }
+    }
+
+    function showOAuthError($msg)
+    {
+        header('HTTP/1.1 401 Unauthorized');
+        header('Content-Type: text/html; charset=utf-8');
+        print $msg . "\n";
+    }
 
     /**
      * Does this API resource require authentication?
@@ -70,18 +205,24 @@ class ApiAuthAction extends ApiAction
     {
         $this->basicAuthProcessHeader();
 
+        $realm = common_config('site', 'name') . ' API';
+
         if (!isset($this->auth_user)) {
-            header('WWW-Authenticate: Basic realm="StatusNet API"');
+            header('WWW-Authenticate: Basic realm="' . $realm . '"');
 
             // show error if the user clicks 'cancel'
 
             $this->showBasicAuthError();
-            return false;
+            exit;
 
         } else {
             $nickname = $this->auth_user;
             $password = $this->auth_pw;
-            $this->auth_user = common_check_user($nickname, $password);
+            $user = common_check_user($nickname, $password);
+            if (Event::handle('StartSetApiUser', array(&$user))) {
+                $this->auth_user = $user;
+                Event::handle('EndSetApiUser', array($user));
+            }
 
             if (empty($this->auth_user)) {
 
@@ -94,9 +235,10 @@ class ApiAuthAction extends ApiAction
                     "$nickname, proxy = $proxy, ip = $ip."
                 );
                 $this->showBasicAuthError();
-                return false;
+                exit;
             }
         }
+
         return true;
     }
 
@@ -152,7 +294,7 @@ class ApiAuthAction extends ApiAction
         header('HTTP/1.1 401 Unauthorized');
         $msg = 'Could not authenticate you.';
 
-        if ($this->arg('format') == 'xml') {
+        if ($this->format == 'xml') {
             header('Content-Type: application/xml; charset=utf-8');
             $this->startXML();
             $this->elementStart('hash');
@@ -160,7 +302,7 @@ class ApiAuthAction extends ApiAction
             $this->element('request', null, $_SERVER['REQUEST_URI']);
             $this->elementEnd('hash');
             $this->endXML();
-        } elseif ($this->arg('format') == 'json') {
+        } elseif ($this->format == 'json') {
             header('Content-Type: application/json; charset=utf-8');
             $error_array = array('error' => $msg,
                                  'request' => $_SERVER['REQUEST_URI']);