一度ブログでも大絶賛した、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に登録しておけば、次回からは自動的にログインをして貰うこともできます。
また、つぶやきのプログラムなどを作ったらブログに投稿します。
大変分かりやすいエントリーありがとうございます。
質問させてください。書かれている内容を再現したのですが、
「Unable to load the requested file: helpers/oauth_helper.php」
というエラーが表示されます。
原因としては、標準のヘルパーの中にはOAuthヘルパーは存在しないので、
エラーとなる、と読み取ったのですが、まず、この認識で間違いないでしょうか?
また、そうであれば、Web上で配布されているものダウンロードして、適切なディレクトリに配置する、あるいは自作する必要があると思うのですが、
Google検索などでは、それに関する情報が見つかりませんでした。
どのように対処したのか、教えていただけないでしょうか?
コメントありがとうございます。確かに、ヘルパが必要だったかも知れませんね。。情報が足りなくて申し訳ないです。
ヘルパを読み込むには、
/app/config/autoload.php
ファイルの
$autoload['helper'] = array();
という記述がある箇所に、そのヘルパ名を書き込むだけで良いです。例えば、oauthなら
$autoload['helper'] = array(‘oauth’);
という具合に。ちょっと試してみてくださいー。
返答ありがとうございます。
自分の書き方が悪かったようです。
教えていただきたかったのは、ヘルパーの読み込み方ではなく
「oauth_helper.php」というファイル自体の入手先でした。
これに関しては、その後、ライブラリと同じwikiの方で発見しました。
お騒がせしました。
有用な情報を発信させてるので、引き続きよろしくお願いいたします。
ありがとうございました。
ありゃ、ごめんなさい・・私も参照しながら作業しているときに、なにをやったか忘れてしまっておりました。。
今後も、役に立たないエントリーを投稿しますが、なにとぞお付き合いくださいませ!