diff --git a/actions/apioauthrequesttoken.php b/actions/apioauthrequesttoken.php index 4fa626d866..4f4c2c8fb2 100644 --- a/actions/apioauthrequesttoken.php +++ b/actions/apioauthrequesttoken.php @@ -2,7 +2,7 @@ /** * StatusNet, the distributed open-source microblogging tool * - * Get an OAuth request token + * Issue temporary OAuth credentials (a request token) * * PHP version 5 * @@ -34,7 +34,7 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR . '/lib/apioauth.php'; /** - * Get an OAuth request token + * Issue temporary OAuth credentials (a request token) * * @category API * @package StatusNet @@ -58,22 +58,23 @@ class ApiOauthRequestTokenAction extends ApiOauthAction { parent::prepare($args); - $this->callback = $this->arg('oauth_callback'); - - if (!empty($this->callback)) { - common_debug("callback: $this->callback"); - } + // XXX: support "force_login" parameter like Twitter? (Forces the user to enter + // their credentials to ensure the correct users account is authorized.) return true; } /** - * Class handler. + * Handle a request for temporary OAuth credentials + * + * Make sure the request is kosher, then emit a set of temporary + * credentials -- AKA an unauthorized request token. * * @param array $args array of arguments * * @return void */ + function handle($args) { parent::handle($args); @@ -85,14 +86,63 @@ class ApiOauthRequestTokenAction extends ApiOauthAction $server->add_signature_method($hmac_method); try { + $req = OAuthRequest::from_request(); + + // verify callback + if (!$this->verifyCallback($req->get_parameter('oauth_callback'))) { + throw new OAuthException( + "You must provide a valid URL or 'oob' in oauth_callback.", + 400 + ); + } + + // check signature and issue a new request token $token = $server->fetch_request_token($req); - print $token; + + // return token to the client + $this->showRequestToken($token); + } catch (OAuthException $e) { common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage()); - header('HTTP/1.1 401 Unauthorized'); - header('Content-Type: text/html; charset=utf-8'); - print $e->getMessage() . "\n"; + + // Return 401 for for bad credentials or signature problems, + // and 400 for missing or unsupported parameters + + $code = $e->getCode(); + $this->clientError($e->getMessage(), empty($code) ? 401 : $code, 'text'); + } + } + + /* + * Display temporary OAuth credentials + */ + + function showRequestToken($token) + { + header('Content-Type: application/x-www-form-urlencoded'); + print $token; + print '&oauth_callback_confirmed=true'; + } + + /* Make sure the callback parameter contains either a real URL + * or the string 'oob'. + * + * @todo Check for evil/banned URLs here + * + * @return boolean true or false + */ + + function verifyCallback($callback) + { + if ($callback == "oob") { + common_debug("OAuth request token requested for out of bounds client."); + return true; + } else { + return Validate::uri( + $callback, + array('allowed_schemes' => array('http', 'https')) + ); } } diff --git a/lib/apioauth.php b/lib/apioauth.php index b2d8faa5a5..75b0b3c576 100644 --- a/lib/apioauth.php +++ b/lib/apioauth.php @@ -77,6 +77,11 @@ class ApiOauthAction extends ApiAction self::cleanRequest(); } + /* + * Clean up the request so the OAuth library doesn't find + * any extra parameters or anything else it's not expecting. + * I'm looking at you, p parameter. + */ static function cleanRequest() { // kill evil effects of magical slashing