Пример #1
0
 static function getByKeys($user, $app)
 {
     if (empty($user) || empty($app)) {
         return null;
     }
     $oau = new Oauth_application_user();
     $oau->profile_id = $user->id;
     $oau->application_id = $app->id;
     $oau->limit(1);
     $result = $oau->find(true);
     return empty($result) ? null : $oau;
 }
Пример #2
0
 static function getByUserAndToken($user, $token)
 {
     if (empty($user) || empty($token)) {
         return null;
     }
     $oau = new Oauth_application_user();
     $oau->profile_id = $user->id;
     $oau->token = $token;
     $oau->limit(1);
     $result = $oau->find(true);
     return empty($result) ? null : $oau;
 }
 private function newAppUser($tokenAssoc, $app, $at)
 {
     $appUser = new Oauth_application_user();
     $appUser->profile_id = $tokenAssoc->profile_id;
     $appUser->application_id = $app->id;
     $appUser->access_type = $app->access_type;
     $appUser->token = $at->tok;
     $appUser->created = common_sql_now();
     $result = $appUser->insert();
     if (!$result) {
         common_log_db_error($appUser, 'INSERT', __FILE__);
         throw new Exception(_('Database error inserting OAuth application user.'));
     }
 }
Пример #4
0
 /**
  * Verifies the OAuth request signature, sets the auth user
  * and access type (read-only or read-write)
  *
  * @param OAuthRequest $request the OAuth Request
  *
  * @return nothing
  */
 function checkOAuthRequest($request)
 {
     $datastore = new ApiGNUsocialOAuthDataStore();
     $server = new OAuthServer($datastore);
     $hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
     $server->add_signature_method($hmac_method);
     try {
         $server->verify_request($request);
         $consumer = $request->get_parameter('oauth_consumer_key');
         $access_token = $request->get_parameter('oauth_token');
         $app = Oauth_application::getByConsumerKey($consumer);
         if (empty($app)) {
             common_log(LOG_WARNING, 'API OAuth - Couldn\'t find the OAuth app for consumer key: ' . $consumer);
             // TRANS: OAuth exception thrown when no application is found for a given consumer key.
             throw new OAuthException(_('No application for that consumer key.'));
         }
         // set the source attr
         if ($app->name != 'anonymous') {
             $this->source = $app->name;
         }
         $appUser = Oauth_application_user::getKV('token', $access_token);
         if (!empty($appUser)) {
             // If access_type == 0 we have either a request token
             // or a bad / revoked access token
             if ($appUser->access_type != 0) {
                 // Set the access level for the api call
                 $this->access = $appUser->access_type & Oauth_application::$writeAccess ? self::READ_WRITE : self::READ_ONLY;
                 // Set the auth user
                 if (Event::handle('StartSetApiUser', array(&$user))) {
                     $user = User::getKV('id', $appUser->profile_id);
                     if (!empty($user)) {
                         if (!$user->hasRight(Right::API)) {
                             // TRANS: Authorization exception thrown when a user without API access tries to access the API.
                             throw new AuthorizationException(_('Not allowed to use API.'));
                         }
                     }
                     $this->auth_user = $user;
                     // FIXME: setting the value returned by common_current_user()
                     // There should probably be a better method for this. common_set_user()
                     // does lots of session stuff.
                     global $_cur;
                     $_cur = $this->auth_user;
                     Event::handle('EndSetApiUser', array($user));
                 }
                 $msg = "API OAuth authentication for user '%s' (id: %d) on behalf of " . "application '%s' (id: %d) with %s access.";
                 common_log(LOG_INFO, sprintf($msg, $this->auth_user->nickname, $this->auth_user->id, $app->name, $app->id, ($this->access = self::READ_WRITE) ? 'read-write' : 'read-only'));
             } else {
                 // TRANS: OAuth exception given when an incorrect access token was given for a user.
                 throw new OAuthException(_('Bad access token.'));
             }
         } else {
             // Also should not happen.
             // TRANS: OAuth exception given when no user was found for a given token (no token was found).
             throw new OAuthException(_('No user for that token.'));
         }
     } catch (OAuthException $e) {
         $this->logAuthFailure($e->getMessage());
         common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage());
         $this->clientError($e->getMessage(), 401);
     }
 }
Пример #5
0
 /**
  * Verifies the OAuth request signature, sets the auth user
  * and access type (read-only or read-write)
  *
  * @param OAuthRequest $request the OAuth Request
  *
  * @return nothing
  */
 function checkOAuthRequest($request)
 {
     $datastore = new ApiStatusNetOAuthDataStore();
     $server = new OAuthServer($datastore);
     $hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
     $server->add_signature_method($hmac_method);
     try {
         $server->verify_request($request);
         $consumer = $request->get_parameter('oauth_consumer_key');
         $access_token = $request->get_parameter('oauth_token');
         $app = Oauth_application::getByConsumerKey($consumer);
         if (empty($app)) {
             common_log(LOG_WARNING, 'Couldn\'t find the OAuth app for consumer key: ' . $consumer);
             throw new OAuthException('No application for that consumer key.');
         }
         // set the source attr
         $this->source = $app->name;
         $appUser = Oauth_application_user::staticGet('token', $access_token);
         if (!empty($appUser)) {
             // If access_type == 0 we have either a request token
             // or a bad / revoked access token
             if ($appUser->access_type != 0) {
                 // Set the access level for the api call
                 $this->access = $appUser->access_type & Oauth_application::$writeAccess ? self::READ_WRITE : self::READ_ONLY;
                 // Set the auth user
                 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) with %s access.";
                 common_log(LOG_INFO, sprintf($msg, $this->auth_user->nickname, $this->auth_user->id, $app->name, $app->id, ($this->access = self::READ_WRITE) ? 'read-write' : 'read-only'));
             } 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_WARNING, 'API OAuthException - ' . $e->getMessage());
         $this->clientError($e->getMessage(), 401, $this->format);
         exit;
     }
 }
 /**
  * Revoke an access token
  *
  * XXX: Confirm revoke before doing it
  *
  * @param int $appId the ID of the application
  *
  */
 function revokeAccess($token)
 {
     $cur = common_current_user();
     $appUser = Oauth_application_user::getByUserAndToken($cur, $token);
     if (empty($appUser)) {
         // TRANS: Client error when trying to revoke access for an application while not being a user of it.
         $this->clientError(_('You are not a user of that application.'), 401);
         return false;
     }
     $app = Oauth_application::staticGet('id', $appUser->application_id);
     $datastore = new ApiStatusNetOAuthDataStore();
     $datastore->revoke_token($appUser->token, 1);
     $result = $appUser->delete();
     if (!$result) {
         common_log_db_error($orig, 'DELETE', __FILE__);
         // TRANS: Client error when revoking access has failed for some reason.
         // TRANS: %s is the application ID revoking access failed for.
         $this->clientError(sprintf(_('Unable to revoke access for application: %s.'), $app->id));
         return false;
     }
     $msg = 'API OAuth - user %s (id: %d) revoked access token %s for app id %d';
     common_log(LOG_INFO, sprintf($msg, $cur->nickname, $cur->id, $appUser->token, $appUser->application_id));
     $msg = sprintf(_('You have successfully revoked access for %1$s and the access token starting with %2$s.'), $app->name, substr($appUser->token, 0, 7));
     $this->showForm($msg, true);
 }
Пример #7
0
 /**
  * Reset an application's Consumer key and secret
  *
  * XXX: Should this be moved to its own page with a confirm?
  *
  */
 function resetKey()
 {
     $this->application->query('BEGIN');
     $oauser = new Oauth_application_user();
     $oauser->application_id = $this->application->id;
     $result = $oauser->delete();
     if ($result === false) {
         common_log_db_error($oauser, 'DELETE', __FILE__);
         $this->success = false;
         $this->msg = 'Unable to reset consumer key and secret.';
         $this->showPage();
         return;
     }
     $consumer = $this->application->getConsumer();
     $result = $consumer->delete();
     if ($result === false) {
         common_log_db_error($consumer, 'DELETE', __FILE__);
         $this->success = false;
         $this->msg = 'Unable to reset consumer key and secret.';
         $this->showPage();
         return;
     }
     $consumer = Consumer::generateNew();
     $result = $consumer->insert();
     if (empty($result)) {
         common_log_db_error($consumer, 'INSERT', __FILE__);
         $this->application->query('ROLLBACK');
         $this->success = false;
         $this->msg = 'Unable to reset consumer key and secret.';
         $this->showPage();
         return;
     }
     $orig = clone $this->application;
     $this->application->consumer_key = $consumer->consumer_key;
     $result = $this->application->update($orig);
     if ($result === false) {
         common_log_db_error($application, 'UPDATE', __FILE__);
         $this->application->query('ROLLBACK');
         $this->success = false;
         $this->msg = 'Unable to reset consumer key and secret.';
         $this->showPage();
         return;
     }
     $this->application->query('COMMIT');
     $this->success = true;
     $this->msg = 'Consumer key and secret reset.';
     $this->showPage();
 }
 function _deleteAppUsers()
 {
     $oauser = new Oauth_application_user();
     $oauser->application_id = $this->id;
     $oauser->delete();
 }
 function showApplication()
 {
     $user = common_current_user();
     $this->out->elementStart('li', array('class' => 'application', 'id' => 'oauthclient-' . $this->application->id));
     $this->out->elementStart('span', 'vcard author');
     if (!$this->connections) {
         $this->out->elementStart('a', array('href' => common_local_url('showapplication', array('id' => $this->application->id)), 'class' => 'url'));
     } else {
         $this->out->elementStart('a', array('href' => $this->application->source_url, 'class' => 'url'));
     }
     if (!empty($this->application->icon)) {
         $this->out->element('img', array('src' => $this->application->icon, 'class' => 'photo avatar'));
     }
     $this->out->element('span', 'fn', $this->application->name);
     $this->out->elementEnd('a');
     $this->out->elementEnd('span');
     $this->out->raw(' by ');
     $this->out->element('a', array('href' => $this->application->homepage, 'class' => 'url'), $this->application->organization);
     $this->out->element('p', 'note', $this->application->description);
     $this->out->elementEnd('li');
     if ($this->connections) {
         $appUser = Oauth_application_user::getByKeys($this->owner, $this->application);
         if (empty($appUser)) {
             common_debug("empty appUser!");
         }
         $this->out->elementStart('li');
         $access = $this->application->access_type & Oauth_application::$writeAccess ? 'read-write' : 'read-only';
         $txt = 'Approved ' . common_date_string($appUser->modified) . " - {$access} access.";
         $this->out->raw($txt);
         $this->out->elementEnd('li');
         $this->out->elementStart('li', 'entity_revoke');
         $this->out->elementStart('form', array('id' => 'form_revoke_app', 'class' => 'form_revoke_app', 'method' => 'POST', 'action' => common_local_url('oauthconnectionssettings')));
         $this->out->elementStart('fieldset');
         $this->out->hidden('id', $this->application->id);
         $this->out->hidden('token', common_session_token());
         $this->out->submit('revoke', _('Revoke'));
         $this->out->elementEnd('fieldset');
         $this->out->elementEnd('form');
         $this->out->elementEnd('li');
     }
 }
Пример #10
0
 function new_access_token($token, $consumer)
 {
     common_debug('new_access_token("' . $token->key . '","' . $consumer->key . '")', __FILE__);
     $rt = new Token();
     $rt->consumer_key = $consumer->key;
     $rt->tok = $token->key;
     $rt->type = 0;
     // request
     $app = Oauth_application::getByConsumerKey($consumer->key);
     if (empty($app)) {
         common_debug("empty app!");
     }
     if ($rt->find(true) && $rt->state == 1) {
         // authorized
         common_debug('request token found.', __FILE__);
         // find the associated user of the app
         $appUser = new Oauth_application_user();
         $appUser->application_id = $app->id;
         $appUser->token = $rt->tok;
         $result = $appUser->find(true);
         if (!empty($result)) {
             common_debug("Oath app user found.");
         } else {
             common_debug("Oauth app user not found. app id {$app->id} token {$rt->tok}");
             return null;
         }
         // go ahead and make the access token
         $at = new Token();
         $at->consumer_key = $consumer->key;
         $at->tok = common_good_rand(16);
         $at->secret = common_good_rand(16);
         $at->type = 1;
         // access
         $at->created = DB_DataObject_Cast::dateTime();
         if (!$at->insert()) {
             $e = $at->_lastError;
             common_debug('access token "' . $at->tok . '" not inserted: "' . $e->message . '"', __FILE__);
             return null;
         } else {
             common_debug('access token "' . $at->tok . '" inserted', __FILE__);
             // burn the old one
             $orig_rt = clone $rt;
             $rt->state = 2;
             // used
             if (!$rt->update($orig_rt)) {
                 return null;
             }
             common_debug('request token "' . $rt->tok . '" updated', __FILE__);
             // update the token from req to access for the user
             $orig = clone $appUser;
             $appUser->token = $at->tok;
             // It's at this point that we change the access type
             // to whatever the application's access is.  Request
             // tokens should always have an access type of 0, and
             // therefore be unuseable for making requests for
             // protected resources.
             $appUser->access_type = $app->access_type;
             $result = $appUser->update($orig);
             if (empty($result)) {
                 common_debug('couldn\'t update OAuth app user.');
                 return null;
             }
             // Okay, good
             return new OAuthToken($at->tok, $at->secret);
         }
     } else {
         return null;
     }
 }
Пример #11
0
 function getConnectedApps($offset = 0, $limit = null)
 {
     $qry = 'SELECT u.* ' . 'FROM oauth_application_user u, oauth_application a ' . 'WHERE u.profile_id = %d ' . 'AND a.id = u.application_id ' . 'AND u.access_type > 0 ' . 'ORDER BY u.created DESC ';
     if ($offset > 0) {
         if (common_config('db', 'type') == 'pgsql') {
             $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
         } else {
             $qry .= ' LIMIT ' . $offset . ', ' . $limit;
         }
     }
     $apps = new Oauth_application_user();
     $cnt = $apps->query(sprintf($qry, $this->id));
     return $apps;
 }
Пример #12
0
 function new_access_token($token, $consumer, $verifier)
 {
     common_debug(sprintf("New access token from request token %s, consumer %s and verifier %s ", $token, $consumer, $verifier), __FILE__);
     $rt = new Token();
     $rt->consumer_key = $consumer->key;
     $rt->tok = $token->key;
     $rt->type = 0;
     // request
     $app = Oauth_application::getByConsumerKey($consumer->key);
     assert(!empty($app));
     if ($rt->find(true) && $rt->state == 1 && $rt->verifier == $verifier) {
         // authorized
         common_debug('Request token found.', __FILE__);
         // find the app and profile associated with this token
         $tokenAssoc = Oauth_token_association::staticGet('token', $rt->tok);
         if (!$tokenAssoc) {
             throw new Exception(_('Could not find a profile and application associated with the request token.'));
         }
         // check to see if we have previously issued an access token for this application
         // and profile
         $appUser = new Oauth_application_user();
         $appUser->application_id = $app->id;
         $appUser->profile_id = $tokenAssoc->profile_id;
         $result = $appUser->find(true);
         if (!empty($result)) {
             common_log(LOG_INFO, sprintf("Existing access token found for application %s, profile %s.", $app->id, $tokenAssoc->profile_id));
             $at = new Token();
             // fetch the full access token
             $at->consumer_key = $consumer->key;
             $at->tok = $appUser->token;
             $result = $at->find(true);
             if (!$result) {
                 throw new Exception(_('Could not issue access token.'));
             }
             // Yay, we can re-issue the access token
             return new OAuthToken($at->tok, $at->secret);
         } else {
             common_log(LOG_INFO, sprintf("Creating new access token for application %s, profile %s.", $app->id, $tokenAssoc->profile_id));
             // make a brand new access token
             $at = new Token();
             $at->consumer_key = $consumer->key;
             $at->tok = common_good_rand(16);
             $at->secret = common_good_rand(16);
             $at->type = 1;
             // access
             $at->verifier = $verifier;
             $at->verified_callback = $rt->verified_callback;
             // 1.0a
             $at->created = common_sql_now();
             if (!$at->insert()) {
                 $e = $at->_lastError;
                 common_debug('access token "' . $at->tok . '" not inserted: "' . $e->message . '"', __FILE__);
                 return null;
             } else {
                 common_debug('access token "' . $at->tok . '" inserted', __FILE__);
                 // burn the old one
                 $orig_rt = clone $rt;
                 $rt->state = 2;
                 // used
                 if (!$rt->update($orig_rt)) {
                     return null;
                 }
                 common_debug('request token "' . $rt->tok . '" updated', __FILE__);
             }
             // insert a new Oauth_application_user record w/access token
             $appUser = new Oauth_application_user();
             $appUser->profile_id = $tokenAssoc->profile_id;
             $appUser->application_id = $app->id;
             $appUser->access_type = $app->access_type;
             $appUser->token = $at->tok;
             $appUser->created = common_sql_now();
             $result = $appUser->insert();
             if (!$result) {
                 common_log_db_error($appUser, 'INSERT', __FILE__);
                 // TRANS: Server error displayed when a database error occurs.
                 $this->serverError(_('Database error inserting OAuth application user.'));
             }
             // Okay, good
             return new OAuthToken($at->tok, $at->secret);
         }
     } else {
         // the token was not authorized or not verfied
         common_log(LOG_INFO, sprintf("API OAuth - Attempt to exchange unauthorized or unverified request token %s for an access token.", $rt->tok));
         return null;
     }
 }
 function handlePost()
 {
     // check session token for CSRF protection.
     $token = $this->trimmed('token');
     if (!$token || $token != common_session_token()) {
         $this->showForm(_('There was a problem with your session token. ' . 'Try again, please.'));
         return;
     }
     // check creds
     $user = null;
     if (!common_logged_in()) {
         $user = common_check_user($this->nickname, $this->password);
         if (empty($user)) {
             $this->showForm(_("Invalid nickname / password!"));
             return;
         }
     } else {
         $user = common_current_user();
     }
     if ($this->arg('allow')) {
         // mark the req token as authorized
         $this->store->authorize_token($this->oauth_token);
         // Check to see if there was a previous token associated
         // with this user/app and kill it. If the user is doing this she
         // probably doesn't want any old tokens anyway.
         $appUser = Oauth_application_user::getByKeys($user, $this->app);
         if (!empty($appUser)) {
             $result = $appUser->delete();
             if (!$result) {
                 common_log_db_error($appUser, 'DELETE', __FILE__);
                 throw new ServerException(_('Database error deleting OAuth application user.'));
                 return;
             }
         }
         // associated the authorized req token with the user and the app
         $appUser = new Oauth_application_user();
         $appUser->profile_id = $user->id;
         $appUser->application_id = $this->app->id;
         // Note: do not copy the access type from the application.
         // The access type should always be 0 when the OAuth app
         // user record has a request token associated with it.
         // Access type gets assigned once an access token has been
         // granted.  The OAuth app user record then gets updated
         // with the new access token and access type.
         $appUser->token = $this->oauth_token;
         $appUser->created = common_sql_now();
         $result = $appUser->insert();
         if (!$result) {
             common_log_db_error($appUser, 'INSERT', __FILE__);
             throw new ServerException(_('Database error inserting OAuth application user.'));
             return;
         }
         // if we have a callback redirect and provide the token
         // A callback specified in the app setup overrides whatever
         // is passed in with the request.
         if (!empty($this->app->callback_url)) {
             $this->callback = $this->app->callback_url;
         }
         if (!empty($this->callback)) {
             $target_url = $this->getCallback($this->callback, array('oauth_token' => $this->oauth_token));
             common_redirect($target_url, 303);
         } else {
             common_debug("callback was empty!");
         }
         // otherwise inform the user that the rt was authorized
         $this->elementStart('p');
         // XXX: Do OAuth 1.0a verifier code
         $this->raw(sprintf(_("The request token %s has been authorized. " . 'Please exchange it for an access token.'), $this->oauth_token));
         $this->elementEnd('p');
     } else {
         if ($this->arg('deny')) {
             $datastore = new ApiStatusNetOAuthDataStore();
             $datastore->revoke_token($this->oauth_token, 0);
             $this->elementStart('p');
             $this->raw(sprintf(_("The request token %s has been denied and revoked."), $this->oauth_token));
             $this->elementEnd('p');
         } else {
             $this->clientError(_('Unexpected form submission.'));
             return;
         }
     }
 }
Пример #14
0
 function showApplication()
 {
     $user = common_current_user();
     $this->out->elementStart('li', array('class' => 'application', 'id' => 'oauthclient-' . $this->application->id));
     $this->out->elementStart('span', 'vcard author');
     if (!$this->connections) {
         $this->out->elementStart('a', array('href' => common_local_url('showapplication', array('id' => $this->application->id)), 'class' => 'url'));
     } else {
         $this->out->elementStart('a', array('href' => $this->application->source_url, 'class' => 'url'));
     }
     if (!empty($this->application->icon)) {
         $this->out->element('img', array('src' => $this->application->icon, 'class' => 'photo avatar'));
     }
     $this->out->element('span', 'fn', $this->application->name);
     $this->out->elementEnd('a');
     $this->out->elementEnd('span');
     $this->out->raw(' by ');
     $this->out->element('a', array('href' => $this->application->homepage, 'class' => 'url'), $this->application->organization);
     $this->out->element('p', 'note', $this->application->description);
     $this->out->elementEnd('li');
     if ($this->connections) {
         $appUser = Oauth_application_user::getByKeys($this->owner, $this->application);
         if (empty($appUser)) {
             common_debug("empty appUser!");
         }
         $this->out->elementStart('li');
         // TRANS: Application access type
         $readWriteText = _('read-write');
         // TRANS: Application access type
         $readOnlyText = _('read-only');
         $access = $this->application->access_type & Oauth_application::$writeAccess ? $readWriteText : $readOnlyText;
         $modifiedDate = common_date_string($appUser->modified);
         // TRANS: Used in application list. %1$s is a modified date, %2$s is access type (read-write or read-only)
         $txt = sprintf(_('Approved %1$s - "%2$s" access.'), $modifiedDate, $access);
         $this->out->raw($txt);
         $this->out->elementEnd('li');
         $this->out->elementStart('li', 'entity_revoke');
         $this->out->elementStart('form', array('id' => 'form_revoke_app', 'class' => 'form_revoke_app', 'method' => 'POST', 'action' => common_local_url('oauthconnectionssettings')));
         $this->out->elementStart('fieldset');
         $this->out->hidden('id', $this->application->id);
         $this->out->hidden('token', common_session_token());
         // TRANS: Button label
         $this->out->submit('revoke', _m('BUTTON', 'Revoke'));
         $this->out->elementEnd('fieldset');
         $this->out->elementEnd('form');
         $this->out->elementEnd('li');
     }
 }
 /**
  * Revoke access to an authorized OAuth application
  *
  * @param int $appId the ID of the application
  *
  */
 function revokeAccess($appId)
 {
     $cur = common_current_user();
     $app = Oauth_application::staticGet('id', $appId);
     if (empty($app)) {
         $this->clientError(_('No such application.'), 404);
         return false;
     }
     // XXX: Transaction here?
     $appUser = Oauth_application_user::getByKeys($cur, $app);
     if (empty($appUser)) {
         $this->clientError(_('You are not a user of that application.'), 401);
         return false;
     }
     $datastore = new ApiStatusNetOAuthDataStore();
     $datastore->revoke_token($appUser->token, 1);
     $result = $appUser->delete();
     if (!$result) {
         common_log_db_error($orig, 'DELETE', __FILE__);
         $this->clientError(sprintf(_('Unable to revoke access for app: %s.'), $app->id));
         return false;
     }
     $msg = 'User %s (id: %d) revoked access to app %s (id: %d)';
     common_log(LOG_INFO, sprintf($msg, $cur->nickname, $cur->id, $app->name, $app->id));
 }