Hatena::ブログ(Diary)

更新しない備忘録改

2011-06-08

PHPでTwitterのOAuth認証をする

昔のブログで書いたものの焼き直しです(割とアクセス数多かったので)。

タイトルのことを知り合いに聞かれたんですが、自分もOAuthに関しては少し怪しかったので、勉強がてらソースを作りました。
しかし、Webですぐに見つかる資料だと、ちょっと情報が足りなかったりして困りましたね。。。
ひとまず作ったものでOAuth認証API動作などを確認したので、以下に情報を載せます。

OAuth認証の概略

OAuthの詳しい話はいきなり省略しますが、要はユーザが「私はこのアプリケーションを信頼しますよ」というメッセージをTwitterなりのサービスに送って、アプリケーションとサービスの間で好きに通信できるようにする仕組みです。
(なお、OAuthではサービスと通信するアプリケーションをコンシューマと言うようです)
ここで、OAuthで通信しようとするアプリケーションは、通信のための鍵が必要になります。最低限必要な鍵は、次の2つです。

  • コンシューマ・キー
  • ユーザのアクセス・トークン

コンシューマ・キーはサービス側でアプリケーションを識別するためのもので、アクセス・トークンはユーザを識別するものです。この2個を組み合わせて使用することにより、「どのユーザがどのアプリケーションを使ってアクセスしている」ということが分かります。
また、実際にはそれぞれの鍵が「公開鍵」と「秘密鍵」の2個で一組になっており、実際に覚えておく必要のある鍵は計4個になります。

アプリケーションの前準備

ではまず、アプリケーションTwitterと通信できるようにするために、コンシューマ・キーを取得します。
……と言っても、これはタダでいくらでも貰えるわけではなく、Twitterアプリケーションを登録する必要があります。
最初にTwitterログインしておき、下のページ(Twitterの開発者用サイト)を訪れます。

http://dev.twitter.com/

ここの、「Your app」という項目を選択すると、「新しいアプリケーションを登録する」というボタンがあるので、それをクリックします。
すると、アプリケーションの登録ページになります。ここの項目を埋めて、下のボタンを押せば登録完了です。
それぞれの項目は次の意味になります。


アプリケーションアプリケーションの名前。Tweetしたときに出る「ドコドコから」という情報は、ここに設定した文字が使われる。
アプリケーションの説明そのまんま。
アプリケーションウェブサイトURLアプリケーションを置いているURLを指定する。今回はPHPなので、スクリプトの置いてあるページのアドレスそのままでいい。
所属会社/団体そのまんま。自分の場合は大学の略号を入力。
アプリケーションの種類クライアントアプリケーションブラウザアプリケーションを選ぶ。今回はPHPブラウザで動かすので、ブラウザアプリケーションを選択。
コールバックURLTwitterの認証画面から帰るときに飛ぶURLを指定する。今回はウェブサイトURLと同じにした(同じスクリプトファイルで動作させてるので)。実は書かなくても問題ないみたい。
Default Access typeRead & WriteかRead-onlyを選ぶ。Read & Writeは、投稿など、Twitter側の情報を変更する処理を行う場合に選ぶ。ただデータを読み込みたいだけならRead-onlyを選ぶ。
アプリケーションアイコンアプリケーションを識別するアイコン

登録が終わると、アプリケーションの登録情報が表示されます。このうち、「Consumer key」と「Consumer secret」が、それぞれアプリケーションのコンシューマ・キー(公開鍵と秘密鍵)になります。これをどこかに控えておきます。
また、横のメニューの「My Access Token」というのを選択すると、いまログインしているユーザ(おそらく開発者)のアクセス・トークンが得られます。このユーザでBOTなどを作る場合は、こちらも控えておきましょう。

さて、ここからはプログラミングの番です。
さすがにOAuth認証全体を自分でコーディングするのは辛いので、ここではSDN Projectさんのページでも紹介されている、Twitter API Wikiabraham's twitteroauth 0.2.0を使います。

(コード・リポジトリhttp://github.com/abraham/twitteroauth

このライブラリはよく出来ていて、アプリケーションとサービス間の主な通信部分は、全部内部でやってくれます。
リポジトリからダウンロードしたものを見ると、twitteroauth.phpOAuth.phpが入っています。twitteroauth.phpが、我々が実際に使うライブラリです。OAuth.phpOAuth認証の根幹部分を構成するライブラリで、twitteroauth.phpから呼び出して使用されています。
とりあえず、自分のコードの先頭でtwitteroauth.phpをrequireしましょう。

require_once('twitteroauth.php');

twitteroauth.phpには、TwitterOAuthというクラスが宣言されており、これがアプリケーション側の通信クライアントになります。認証や実際のデータ送受信などは、このクラスを通して行うことになります。
ただし、ユーザのアクセス・トークンが分かっている場合とそうでない場合で、やるべき処理が少し違います。

アクセス・トークンが分かっている場合

BOTを作成するときなど、自分のアクセス・トークンを使用する場合がこれに当たります。
これは既に認証完了しているのと同じなので、以下のように、単純にTwitterOAuthクラスのインスタンスを作成すれば、もう通信可能です。

// アプリケーションのコンシューマ・キー
$consumer_key = 'hoge';
$consumer_secret = 'piyo';
// ユーザのアクセス・トークン
$oauth_token = 'fuga';
$oauth_token_secret = 'hogera';

// クライアントの作成
$client = new TwitterOAuth(
	$consumer_key, $consumer_secret,
	$oauth_token, $oauth_token_secret);

不特定多数のユーザが使用する場合

この場合はアクセス・トークンが分からないので、その取得作業が必要になります。
Twitter対応のWebアプリケーションを使おうとすると、一度Twitterの認証画面が表示されますね。あれを実装するわけです。

まず、アクセス・トークンを取得するまでの一連の流れを以下の図に示します。
f:id:yus_iri:20110609044328p:image

手順も多いのですが、WebアプリケーションOAuthを一層ややこしくしているのは、1回のPHP実行で認証が完了しないからです。ユーザは一度Twitterに行って再度戻ってくるため、認証完了までに計2回、アプリケーションにアクセスすることになります。また、すでに認証済みの場合を考えると、ユーザがアプリケーションにアクセスしてくるのは、以下の3パターンということになります。

  • 未認証
  • 認証画面から帰ってきた
  • 既に認証済み

以下では、これらを順を追って説明します。

1. ユーザが未認証のとき

サイトに初めてアクセスしてきた場合、もしくはログアウトをした後などでは、アプリケーションはユーザのアクセス・トークンを全く知りません。このときはまず、ユーザにTwitterの認証ページへ行ってもらい、認証作業をしてもらう必要があります。

まずアプリケーションは、リクエスト・トークンと呼ばれる、認証用のトークンをTwitterに発行してもらいます。このときアプリケーションTwitterに渡す情報は、アプリケーションのコンシューマ・キーと、認証後に戻るためのURL(コールバックURL)です。発行されたトークンには、これらの情報が関連付けられます。

次に、リクエスト・トークンの公開鍵をユーザに渡し、ユーザはこの鍵と自分のアカウント情報を使い、Twitterで認証確認を行います。
アプリケーション側の作業としては、Twitterの認証画面へのURLに、リクエスト・トークンをURLパラメータとして付与したものをユーザに提示します。
リクエスト・トークンは認証後の作業で使用するので、セッションに記憶しておきます。

// アプリケーションのコンシューマ・キー
$consumer_key = 'hoge';
$consumer_secret = 'piyo';
// アプリケーションのアドレス
$app_addr = 'http://www.example.com/';

// セッション起動
session_start();

// Twitterクライアント起動
$client = new TwitterOAuth($consumer_key, $consumer_secret);

// リクエスト・トークンを取得してセッション変数に保存
$token = $client->getRequestToken($app_addr);
$_SESSION['request_token'] = $token['oauth_token'];
$_SESSION['request_token_secret'] = $token['oauth_token_secret'];

// 認証ページのアドレス
$auth_addr = $client->authorizeURL() . '?oauth_token=' . $token['oauth_token'];

/*** ここで$auth_addrにユーザを誘導するHTMLを出力 ***/

2. ユーザが認証画面から帰ってきたとき

ユーザの認証確認が終わると、Twitterは確認コードを発行し、リクエスト・トークンの発行時に設定されたコールバックURLリダイレクトを行います。ここからが認証作業で2度目の実行になります。

リダイレクトURLには、確認コードがURLパラメータとして付与されるので、これをアプリケーション側で受け取ることができます。
アプリケーションは、ユーザの持って帰ってきた確認コードとセッションに記憶していたリクエスト・トークンを組み合わせ、Twitterにアクセス・トークンを発行してもらいます。
うまくアクセス・トークンが取得できれば認証成功です。取得したトークンをセッションデータベースに記憶しておけば、次回のアクセスからは認証作業が必要なくなります。

// アプリケーションのコンシューマ・キー
$consumer_key = 'hoge';
$consumer_secret = 'piyo';
// アプリケーションのアドレス
$app_addr = 'http://www.example.com/';

// セッション起動
session_start();

// Twitterクライアントをリクエスト・トークンで起動
$client = new TwitterOAuth(
	$consumer_key, $consumer_secret,
	$_SESSION['request_token'], $_SESSION['request_token_secret']);

// アクセス・トークンを取得
$token = $client->getAccessToken($_GET['oauth_verifier']);

if (empty($token['oauth_token'])) {
	/*
	 * アクセス・トークンがなければ、何らかの理由で取得失敗した。
	 * もう一度リクエスト・トークンを生成して認証を試みる。
	 */
}

$_SESSION['access_token'] = $token['oauth_token'];
$_SESSION['access_token_secret'] = $token['oauth_token_secret'];

/**** 認証成功、$clientはそのまま通信に使える ***/

3. ユーザが既に認証済みのとき

ユーザのアクセス・トークンを記憶していれば、それを使用することができます。このときは、
前述したBOTなどを作成するときと同じ処理で問題ありません。

// アプリケーションのコンシューマ・キー
$consumer_key = 'hoge';
$consumer_secret = 'piyo';

// セッション起動
session_start();

// クライアントの作成
$client = new TwitterOAuth(
	$consumer_key, $consumer_secret,
	$_SESSION['access_token'], $_SESSION['access_token_secret']);

4. ログアウト(おまけ)

ログアウトの処理は簡単で、セッションデータベースに記憶していたアクセス・トークンを削除するだけです。

unset($_SESSION['access_token']);
unset($_SESSION['access_token_secret']);

コード・サンプル & まとめ

以上を踏まえて、実際に動くコードとしてまとめたものが以下です。

404 Not Found
ソースコードこちら
Twitter APIの仕様変更に対応しました。新しいものはこちら

できることは、ログイン/ログアウトと、ログインしたユーザでのツイートです。機能は簡単ですが、OAuth認証もちゃんと動く、れっきとしたアプリケーションなのです!(笑)

まぁ、こんな感じのコードを書いて、あとは動作を充実させれば、Twitter対応のWebアプリケーションが作れるわけです。
これ以降はTwitter APIの使い方の話になってくるので、ここでは割愛ということで。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

Connection: close