diff --git a/actions/apioauthauthorize.php b/actions/apioauthauthorize.php index 895a0c6e53..48d5087efc 100644 --- a/actions/apioauthauthorize.php +++ b/actions/apioauthauthorize.php @@ -125,19 +125,12 @@ class ApiOauthAuthorizeAction extends Action parent::handle($args); if ($_SERVER['REQUEST_METHOD'] == 'POST') { - /* Use a 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; - } $this->handlePost(); } else { - common_debug('ApiOauthAuthorize::handle()'); + // XXX: make better error messages if (empty($this->oauth_token)) { @@ -160,7 +153,7 @@ class ApiOauthAuthorizeAction extends Action function handlePost() { - /* Use a session token for CSRF protection. */ + // check session token for CSRF protection. $token = $this->trimmed('token'); @@ -175,25 +168,66 @@ class ApiOauthAuthorizeAction extends Action return; } - // is the user already logged in? - // 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 you're doing this you + // probably don'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(_('DB error deleting OAuth app user.')); + return; + } + } + + // associated the new req token with the user and the app + + $appUser = new Oauth_application_user(); + + $appUser->profile_id = $user->id; + $appUser->application_id = $this->app->id; + $appUser->access_type = $this->app->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(_('DB error inserting OAuth app user.')); + return; + } + // if we have a callback redirect and provide the token if (!empty($this->callback)) { + + // XXX: Need better way to build this redirect url. + $target_url = $this->callback . '?oauth_token=' . $this->oauth_token; common_redirect($target_url, 303); } @@ -202,7 +236,7 @@ class ApiOauthAuthorizeAction extends Action $this->elementStart('p'); - // XXX: Do verifier code? + // XXX: Do OAuth 1.0a verifier code? $this->raw(sprintf(_("The request token %s has been authorized. " . 'Please exchange it for an access token.'), @@ -233,7 +267,9 @@ class ApiOauthAuthorizeAction extends Action function showScripts() { parent::showScripts(); - // $this->autofocus('nickname'); + if (!common_logged_in()) { + $this->autofocus('nickname'); + } } /** diff --git a/classes/Oauth_application_user.php b/classes/Oauth_application_user.php index 9e45ece25f..e4c018f219 100644 --- a/classes/Oauth_application_user.php +++ b/classes/Oauth_application_user.php @@ -13,12 +13,34 @@ class Oauth_application_user extends Memcached_DataObject public $profile_id; // int(4) primary_key not_null public $application_id; // int(4) primary_key not_null public $access_type; // tinyint(1) + public $token; // varchar(255) + public $secret; // varchar(255) + public $verifier; // varchar(255) public $created; // datetime not_null + public $modified; // timestamp not_null default_CURRENT_TIMESTAMP /* Static get */ function staticGet($k,$v=NULL) { - return Memcached_DataObject::staticGet('Oauth_application_user',$k,$v); + return Memcached_DataObject::staticGet('Oauth_application_user',$k,$v); } /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + 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; + } + } diff --git a/classes/statusnet.ini b/classes/statusnet.ini index 0cbe60a5a5..43f6c4466d 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -372,7 +372,11 @@ id = N profile_id = 129 application_id = 129 access_type = 17 +token = 2 +secret = 2 +verifier = 2 created = 142 +modified = 384 [oauth_application_user__keys] profile_id = K diff --git a/db/statusnet.sql b/db/statusnet.sql index a2740b60cc..eb47060674 100644 --- a/db/statusnet.sql +++ b/db/statusnet.sql @@ -229,8 +229,11 @@ create table oauth_application_user ( profile_id integer not null comment 'user of the application' references profile (id), application_id integer not null comment 'id of the application' references oauth_application (id), access_type tinyint default 0 comment 'access type, bit 1 = read, bit 2 = write, bit 3 = revoked', + token varchar(255) comment 'authorization token', + secret varchar(255) comment 'token secret', + verifier varchar(255) not null comment 'verification code', created datetime not null comment 'date this record was created', - + modified timestamp comment 'date this record was modified', constraint primary key (profile_id, application_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;