CodeIgniterで、Twitterの OAuthログインを試す

一度ブログでも大絶賛した、CodeIgniterですが、その後もちくちくと触っております。
とにかく手軽で、何でもできるところが良いですね。素敵です。

ということで、試しに Twitterに OAuthログインをする仕組みを作ってみました。これも非常に簡単。ただし、別のところではまったので、メモもかねて。

Twitterでアプリ登録する

まずは、TwitterのDevelopersサイトでアプリの登録をします。

ココではまりポイント。Nameや Descriptionにはアプリ名と説明を記述し、WebSiteにはアプリのURLを記載するのですが、「Callback URL」は必須項目になっていません。そこで、省略して進めてしまうと、後ではまることになるので、ココにも必ず記入しましょう。

後で作りますが、例えば「http://example.com/index.php/tweet/login」などとすると良いでしょう(ドメインは自分のドメインで)

CodeIgniterをインストール

続いて、以下のサイトからCodeIgniterをダウンロードしてセットアップ。

アップロードしたら、/application/config/config.phpを編集して「base_url」にURLを、「encryption_key」に暗号用の適当の文字列を記述します(後でセッションを使う際に利用されます)

ライブラリの作成

今回、元となるプログラムは以下から拝借しました。

まずは、「/application/libraries/twitter_oauth.php」を作ります。

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class twitter_oauth
{
    const SCHEME = 'https';
    const HOST = 'api.twitter.com';
    const AUTHORIZE_URI = '/oauth/authorize';
    const REQUEST_URI   = '/oauth/request_token';
    const ACCESS_URI    = '/oauth/access_token';

    //Array that should contain the consumer secret and
    //key which should be passed into the constructor.
    private $_consumer = false;

    /**
     * Pass in a parameters array which should look as follows:
     * array('key'=>'example.com', 'secret'=>'mysecret');
     * Note that the secret should either be a hash string for
     * HMAC signatures or a file path string for RSA signatures.
     *
     * @param array $params
     */
    public function twitter_oauth($params)
    {
        $this->CI = get_instance();
        $this->CI->load->helper('oauth');

        if(!array_key_exists('method', $params))$params['method'] = 'GET';
        if(!array_key_exists('algorithm', $params))$params['algorithm'] = OAUTH_ALGORITHMS::HMAC_SHA1;

        $this->_consumer = $params;
    }

    /**
     * This is called to begin the oauth token exchange. This should only
     * need to be called once for a user, provided they allow oauth access.
     * It will return a URL that your site should redirect to, allowing the
     * user to login and accept your application.
     *
     * @param string $callback the page on your site you wish to return to
     *                         after the user grants your application access.
     * @return mixed either the URL to redirect to, or if they specified HMAC
     *         signing an array with the token_secret and the redirect url
     */
    public function get_request_token($callback)
    {
        $baseurl = self::SCHEME.'://'.self::HOST.self::REQUEST_URI;

        //Generate an array with the initial oauth values we need
        $auth = build_auth_array($baseurl, $this->_consumer['key'], $this->_consumer['secret'],
                                 array('oauth_callback'=>urlencode($callback)),
                                 $this->_consumer['method'], $this->_consumer['algorithm']);
        //Create the "Authorization" portion of the header
        $str = "";
        foreach($auth as $key => $value)
            $str .= ",{$key}=\"{$value}\"";
        $str = 'Authorization: OAuth '.substr($str, 1);
        //Send it
        $response = $this->_connect($baseurl, $str);
        //We should get back a request token and secret which
        //we will add to the redirect url.
        parse_str($response, $resarray);
        //Return the full redirect url and let the user decide what to do from there.
        $redirect = self::SCHEME.'://'.self::HOST.self::AUTHORIZE_URI."?oauth_token={$resarray['oauth_token']}";
        //If they are using HMAC then we need to return the token secret for them to store.
        if($this->_consumer['algorithm'] == OAUTH_ALGORITHMS::RSA_SHA1)return $redirect;
        else return array('token_secret'=>$resarray['oauth_token_secret'], 'redirect'=>$redirect);
    }

    /**
     * This is called to finish the oauth token exchange. This too should
     * only need to be called once for a user. The token returned should
     * be stored in your database for that particular user.
     *
     * @param string $token this is the oauth_token returned with your callback url
     * @param string $secret this is the token secret supplied from the request (Only required if using HMAC)
     * @param string $verifier this is the oauth_verifier returned with your callback url
     * @return array access token and token secret
     */
    public function get_access_token($token = false, $secret = false, $verifier = false)
    {
        //If no request token was specified then attempt to get one from the url
        if($token === false && isset($_GET['oauth_token']))$token = $_GET['oauth_token'];
        if($verifier === false && isset($_GET['oauth_verifier']))$verifier = $_GET['oauth_verifier'];
        //If all else fails attempt to get it from the request uri.
        if($token === false && $verifier === false)
        {
            $uri = $_SERVER['REQUEST_URI'];
            $uriparts = explode('?', $uri);

            $authfields = array();
            parse_str($uriparts[1], $authfields);
            $token = $authfields['oauth_token'];
            $verifier = $authfields['oauth_verifier'];
        }

        $tokenddata = array('oauth_token'=>urlencode($token), 'oauth_verifier'=>urlencode($verifier));
        if($secret !== false)$tokenddata['oauth_token_secret'] = urlencode($secret);

        $baseurl = self::SCHEME.'://'.self::HOST.self::ACCESS_URI;
        //Include the token and verifier into the header request.
        $auth = get_auth_header($baseurl, $this->_consumer['key'], $this->_consumer['secret'],
                                $tokenddata, $this->_consumer['method'], $this->_consumer['algorithm']);
        $response = $this->_connect($baseurl, $auth);
        //Parse the response into an array it should contain
        //both the access token and the secret key. (You only
        //need the secret key if you use HMAC-SHA1 signatures.)
        parse_str($response, $oauth);
        //Return the token and secret for storage
        return $oauth;
    }

    /**
     * Connects to the server and sends the request,
     * then returns the response from the server.
     * @param <type> $url
     * @param <type> $auth
     * @return <type>
     */
    private function _connect($url, $auth)
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ;
        curl_setopt($ch, CURLOPT_SSLVERSION,3);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array($auth));

        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}
// ./system/application/libraries
?>

これは、先のWikiからコピペしたもの。これをライブラリとして利用します。
つづいて、「/application/controllers/tweet.php」を作って、以下のように記述。

<?php
class Tweet extends CI_Controller {
}

これで「http://example.com/index.php/tweet/login」というURLにアクセスできます。
ビューもモデルも作らなくて良いというのが、気楽です。

それでは、中を作り込んでいきます。まず、先ほどの Twitter Developersサイトでアプリを登録したときに、「Consumer key」と「Consumer secret」というキーを貰えます。これをコピーしておいて、以下のコードに貼り付けます。


<?php
class Tweet extends CI_Controller {
	public function login() {
		$params = array('key'=>'【Consumer key】', 'secret'=>'【Consumer secret】');
		$this->load->library('twitter_oauth', $params);
		$this->load->helper('url');
		$this->load->library('session');

		$response = $this->twitter_oauth->get_request_token(site_url("tweet/callback"));
		$_SESSION['token_secret'] = $response['token_secret'];
		$this->session->set_userdata('token_secret', $response['token_secret']);
		redirect($response['redirect']);
	}

	public function callback() {
		$params = array('key'=>'【Consumer key】', 'secret'=>'【Consumer secret】');
	    $this->load->library('twitter_oauth', $params);
		$this->load->library('session');

	    $response = $this->twitter_oauth->get_access_token(false, $this->session->userdata('token_secret'));
	    //$this->_store_in_db($response);
	    var_dump($response);
	}
}

これでOK。以下のURLにアクセスしてみましょう。

http://example.com/index.php/tweet/login

すると、次のような Twitterの認証画面に移動します。

「Authorize」ボタンをクリックすると、先に「Callback URL」で設定したURLに戻って処理が続行されます。うまくいけば、アカウント名やユーザーIDなどが取得できているでしょう。

上記のプログラムではコメントアウトされていますが、「oauth_token」などをDBに登録しておけば、次回からは自動的にログインをして貰うこともできます。

また、つぶやきのプログラムなどを作ったらブログに投稿します。

4 thoughts on “CodeIgniterで、Twitterの OAuthログインを試す

  1. 大変分かりやすいエントリーありがとうございます。
    質問させてください。書かれている内容を再現したのですが、
    「Unable to load the requested file: helpers/oauth_helper.php」
    というエラーが表示されます。
    原因としては、標準のヘルパーの中にはOAuthヘルパーは存在しないので、
    エラーとなる、と読み取ったのですが、まず、この認識で間違いないでしょうか?

    また、そうであれば、Web上で配布されているものダウンロードして、適切なディレクトリに配置する、あるいは自作する必要があると思うのですが、
    Google検索などでは、それに関する情報が見つかりませんでした。
    どのように対処したのか、教えていただけないでしょうか?

  2. コメントありがとうございます。確かに、ヘルパが必要だったかも知れませんね。。情報が足りなくて申し訳ないです。

    ヘルパを読み込むには、

    /app/config/autoload.php

    ファイルの

    $autoload['helper'] = array();

    という記述がある箇所に、そのヘルパ名を書き込むだけで良いです。例えば、oauthなら

    $autoload['helper'] = array(‘oauth’);

    という具合に。ちょっと試してみてくださいー。

    • 返答ありがとうございます。

      自分の書き方が悪かったようです。
      教えていただきたかったのは、ヘルパーの読み込み方ではなく
      「oauth_helper.php」というファイル自体の入手先でした。

      これに関しては、その後、ライブラリと同じwikiの方で発見しました。
      お騒がせしました。
      有用な情報を発信させてるので、引き続きよろしくお願いいたします。
      ありがとうございました。

      • ありゃ、ごめんなさい・・私も参照しながら作業しているときに、なにをやったか忘れてしまっておりました。。

        今後も、役に立たないエントリーを投稿しますが、なにとぞお付き合いくださいませ!

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>