symfonyとphp-twientでtwitterでログインするサイトをつくる

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

復習。

まず、サイトを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.phpexecuteTwitter メソッド, 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してエラーページ表示してください。