symfonyでつくったウェブサイトでtwitterを使ってログインするようにしてみた。自分でphp-twientというライブラリをつくっておいてもともとクライアント(bot)用だったのとOAuthも忘れてしまっていたので備忘録メモ。

復習。
http://oauth.net/core/1.0/#anchor9
http://oauth.net/core/1.0/#auth_step2

まず、サイトをtwitterにアプリケーション登録する。
http://twitter.com/oauth_clients
サイトなのでApplication TypeをBrowserにして、さらにログインに使うのでYes, use Twitter for login にチェックを入れる。

ここからsymfonyによる開発。今回のメモの実績はsymfony 1.4.2 (sandbox)。

twitterにアプリケーション登録して取得したキーを
/apps/frontend/config/app.yml
に書く

all:
  twitter:
    consumer_key: ’your twitter consumer key'
    consumer_secret: 'your twitter consumer securet'

次にphp-twientを取得して配置する
/path-to-sf_project/lib/vendor/php-twient

php-twientはautoload機能を持っているがとりあえずsymfonyにやらせる
apps/frontend/config/autoload.yml
をつくって以下を書く

autoload:
  php-twient:
    name: php-twient
    path:        %SF_LIB_DIR%/vendor/php-twient/src
    recursive:   on

認証の処理を担当するモジュールを作成する、とりあえずoauthという名前にする

# php symfony generate:module frontend oauth

oauth/twitterというURLで認証実行、oauth/twitter_returnというURLでtwitterからのcallbackを処理する。すなわち
/apps/frontend/modules/oauth/actions/actions.class.php
にexecuteTwitterメソッド,executeTwitter_returnメソッドをそれぞれ実装する

処理の流れとしては
executeTwitter
1) Twitter::oAuth()でサイトのConsumerキーを渡してTwitter_Auth_OAuthを取得
2) Twitter_Auth_OAuth::getRequestTokenにてcallbackを指定してリクエストを投げる
(アプリケーション登録したcallbackとは別のものも指定できるので開発時は重宝する)
3) 成功するとユーザのauthTokenが手に入るのでTwitter_Auth_OAuth::getAuthorizeUrlで認証URLを取得し飛ばす。コールバックに戻ってきたときに使うので一旦このtokenはセッションに入れとく
4) twitterの認証URLでごにょごにょしてユーザが許可したらcallbackのURLに戻ってくる(executeTwitter_returnが実行される)

executeTwitter_return
1) Twitter::oAuthで今度はConsumerキーとセッションに入れてたtokenを使ってTwitter_Auth_OAuthを取得
2) twitterからもらったoauth_verifierをつかってTwitter_Auth_OAuth::getAccessTokenを呼び出す
3) twitter_idを取得できたのでこれをユーザのIDとしてログイン済みとする

コード

class oauthActions extends sfActions
{
     public function executeTwitter(sfWebRequest $request)
     {
          sfContext::getInstance()->getConfiguration()->loadHelpers(array('Url'));
          $twitter = new Twitter();
          $auth = $twitter->oAuth(sfConfig::get('app_twitter_consumer_key'),sfConfig::get('app_twitter_consumer_secret'));
          $token = $auth->getRequestToken(url_for('oauth/twitter_return',true));
          if ($token['oauth_callback_confirmed']) {
               $this->getUser()->setAttribute('oauth_token',$token);
               $this->redirect($auth->getAuthorizeUrl($token));
          }
          return sfView::NONE;
     }
     public function executeTwitter_return(sfWebRequest $request)
     {
          $oauth_token = $request->getParameter('oauth_token');
          $oauth_verifier = $request->getParameter('oauth_verifier');
          $token = $this->getUser()->getAttribute('oauth_token');
          if (!$token || $token['oauth_token'] != $oauth_token) {
               return sfView::ERROR;
          }
          $twitter = new Twitter();
          $auth = $twitter->oAuth(
               sfConfig::get('app_twitter_consumer_key'),
               sfConfig::get('app_twitter_consumer_secret'),
               $token['oauth_token'],
               $token['oauth_token_secret']);
          $token = $auth->getAccessToken($oauth_verifier);

          $this->getUser()->setAuthenticated(true);
          $this->getUser()->setAttribute('twitter_id', $token['user_id']);
          $this->getUser()->setAttribute('twitter_account', $token['screen_name']);
          return sfView::NONE;
     }
}

一応php_twientうごいた。ほっ。symfonyなんか知らんって人でも$request->getParameterを$_REQUEST,
$this->getUser()->getAttribute, $this->getUser()->setAttributeを$_SESSIONに脳内変換してもらえればだいたいわかるはず。

php_twientはエラーは例外吐くので適当にtry-catchしてエラーページ表示してください。