3 * StatusNet, the distributed open-source microblogging tool
5 * Class for doing OAuth authentication against Twitter
9 * LICENCE: This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * @category TwitterauthorizationAction
24 * @author Zach Copely <zach@status.net>
25 * @copyright 2009 StatusNet, Inc.
26 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
27 * @link http://status.net/
30 if (!defined('STATUSNET') && !defined('LACONICA')) {
34 class TwitterauthorizationAction extends Action
37 function prepare($args)
39 parent::prepare($args);
41 $this->oauth_token = $this->arg('oauth_token');
49 * @param array $args is ignored since it's now passed in in prepare()
53 function handle($args)
55 parent::handle($args);
57 if (!common_logged_in()) {
58 $this->clientError(_('Not logged in.'), 403);
61 $user = common_current_user();
62 $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE);
64 // If there's already a foreign link record, it means we already
65 // have an access token, and this is unecessary. So go back.
68 common_redirect(common_local_url('twittersettings'));
71 // $this->oauth_token is only populated once Twitter authorizes our
72 // request token. If it's empty we're at the beginning of the auth
75 if (empty($this->oauth_token)) {
76 $this->authorizeRequestToken();
78 $this->saveAccessToken();
83 * Asks Twitter for a request token, and then redirects to Twitter
88 function authorizeRequestToken()
92 // Get a new request token and authorize it
94 $client = new TwitterOAuthClient();
96 $client->getRequestToken(TwitterOAuthClient::$requestTokenURL);
98 // Sock the request token away in the session temporarily
100 $_SESSION['twitter_request_token'] = $req_tok->key;
101 $_SESSION['twitter_request_token_secret'] = $req_tok->secret;
103 $auth_link = $client->getAuthorizeLink($req_tok);
105 } catch (TwitterOAuthClientException $e) {
106 $msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s',
107 $e->getCode(), $e->getMessage());
108 $this->serverError(_('Couldn\'t link your Twitter account.'));
111 common_redirect($auth_link);
115 * Called when Twitter returns an authorized request token. Exchanges
116 * it for an access token and stores it.
120 function saveAccessToken()
123 // Check to make sure Twitter returned the same request
124 // token we sent them
126 if ($_SESSION['twitter_request_token'] != $this->oauth_token) {
127 $this->serverError(_('Couldn\'t link your Twitter account.'));
132 $client = new TwitterOAuthClient($_SESSION['twitter_request_token'],
133 $_SESSION['twitter_request_token_secret']);
135 // Exchange the request token for an access token
137 $atok = $client->getAccessToken(TwitterOAuthClient::$accessTokenURL);
139 // Test the access token and get the user's Twitter info
141 $client = new TwitterOAuthClient($atok->key, $atok->secret);
142 $twitter_user = $client->verifyCredentials();
144 } catch (OAuthClientException $e) {
145 $msg = sprintf('OAuth client cURL error - code: %1$s, msg: %2$s',
146 $e->getCode(), $e->getMessage());
147 $this->serverError(_('Couldn\'t link your Twitter account.'));
150 // Save the access token and Twitter user info
152 $this->saveForeignLink($atok, $twitter_user);
154 // Clean up the the mess we made in the session
156 unset($_SESSION['twitter_request_token']);
157 unset($_SESSION['twitter_request_token_secret']);
159 common_redirect(common_local_url('twittersettings'));
163 * Saves a Foreign_link between Twitter user and local user,
164 * which includes the access token and secret.
166 * @param OAuthToken $access_token the access token to save
167 * @param mixed $twitter_user twitter API user object
171 function saveForeignLink($access_token, $twitter_user)
173 $user = common_current_user();
175 $flink = new Foreign_link();
177 $flink->user_id = $user->id;
178 $flink->foreign_id = $twitter_user->id;
179 $flink->service = TWITTER_SERVICE;
181 $creds = TwitterOAuthClient::packToken($access_token);
183 $flink->credentials = $creds;
184 $flink->created = common_sql_now();
186 // Defaults: noticesync on, everything else off
188 $flink->set_flags(true, false, false, false);
190 $flink_id = $flink->insert();
192 if (empty($flink_id)) {
193 common_log_db_error($flink, 'INSERT', __FILE__);
194 $this->serverError(_('Couldn\'t link your Twitter account.'));
197 save_twitter_user($twitter_user->id, $twitter_user->screen_name);