PHPでライブラリを使わずにtwitterのOAuth認証を行うサンプル

今更感はありますが、twitterのOAuth認証をライブラリとかは使わないでPHP(curl)のみで行う方法のまとめです。

とりあえず、twitter関連のAPIを使うにはtwitterに開発者登録が必要なので、こちらのページから開発者登録を行いましょう。

開発者登録の詳細は、他のブログ等でいろいろ解説されていますので、そちらを参照してみてください。

開発者登録を行うとconsumer keyとconsumer secretが取得できますので、これをどこかにメモっておいてください。twitter APIの利用の際に使用します。また、API利用の過程で、リクエストトークン取得後にコールバックURLにリダイレクトされますので、その受け口のURLを登録する必要があります。最初の時点で決まって無い場合は後から登録することもできます。

OAuth認証の流れ

OAuth認証の流れは次のような感じになります。

  1. consumer keyとconsumer secretを使って、リクエストトークン(tokenとtoken secret)を取得
  2. リクエストトークンのうちtokenを使って、ユーザにアクセス許可を求めるためのURLを生成し、そのURLにリダイレクト(Webブラウザにはtwitter上のアクセス許可を求めるページが表示されます。)
  3. ブラウザに表示された「許可(allow)」ボタンをユーザが押すと、開発者登録時に入力したコールバックURLにリダイレクトされる
  4. コールバックURLへのアクセスされたら、そのURL中に含まれるoauth_verifierパラメータを取得
  5. consumer key, consumer secret, token, token secret, oauth_verifier を使って、アクセストークン(token2とtoken2 secret)を取得
  6. 以後、consumer key, consumer secret, token2, token2 secret を使って、APIを実行します

リクエストトークンの取得

では、まずは最初のリクエストトークンの取得から説明します。
実際のリクエストトークンの取得ですが、twitter APIの仕様書を見ると次のような感じで書いてあります。

API URL:

  • URL
    http://api.twitter.com/oauth/request_token

引数:

  • oauth_consumer_key (必須)
    アプリケーションの consumer key
  • oauth_nonce (必須)
    ランダムな適当な長さの文字列。使用可能な文字は ASCII コードの 0x21 〜 0x7F の範囲内で printable なもの
  • oauth_signature_method (必須)
    署名方式。Twitter では常に HMAC-SHA1 を指定する
  • oauth_timestamp (必須)
    本リクエストを実行するための処理を開始した日時
  • oauth_version (オプション)
    適用する OAuth のバージョン。Twitter では常に 1.0 を指定する
  • oauth_signature (必須)
    上記パラメータ(oauth_consumer_key ? oauth_version)等を元に生成した文字列を、「アプリケーションの consumer secret(を URL エンコードしたもの)」を暗号鍵として HMAC-SHA1 方式で生成した署名を BASE64 エンコードしたもの

メソッド:

  • GET

応答:

  • トークンの取得に成功すると、以下のような文字列が返る
    oauth_token=トークン&oauth_token_secret=トークンシークレット

これだけの説明だとよく分からないと思いますので、1つずつ説明します。

oauth_consumer_key

開発者登録時に取得したconsumer keyを設定します。

oauth_nonce

ランダムで適当な長さの文字列を設定します。ようは英数字のランダムな文字列ですね。PHPであれば次のような感じでランダムな文字列が生成できます。

md5(uniqid(rand(), true));

oauth_signature_method

この値は HMAC-SHA1 固定でOKです。

oauth_timestamp

いわゆるUNIXタイムスタンプです。処理日時を設定します。ちなみに、この値が現在時刻からかけ離れているとtwitter側からエラーで弾かれます。
PHPだとmktime関数の値をそのまま設定すればOKです。

mktime();

oauth_version

この値は 1.0 固定でOKです。

oauth_signature

この値を生成するのが一番面倒です。
oauth_consumer_key〜oauth_versionまでのパラメータの値をパラメータ名の昇順に並べて、

HTTPのメソッド名&URLエンコードされたAPIのURL&URLエンコードされた昇順に並べたパラメータ文字列

という文字列を生成し、それのSHA1ハッシュを取得し、さらにBASE64エンコードした値ということになります。

文章で説明するだけだと、多分訳が分からないことになると思いますw
なので次のソースを見てもらった方が早いかなと思います。

$api_url = "http://twitter.com/oauth/request_token";

// 必要なパラメータを設定
$param_array = array();
$param_array["oauth_consumer_key"] = "XXXXXXXXX";		// twitterで取得したConsumer key
$param_array["oauth_nonce"] = md5(uniqid(rand(), true));	// ランダムな英数字のみからなる文字列32文字を設定
$param_array["oauth_signature_method"] = "HMAC-SHA1";		// HMAC-SHA1固定
$param_array["oauth_timestamp"] = mktime();			// いわゆるUNIXタイムスタンプ
$param_array["oauth_version"] = "1.0";				// 1.0固定

// パラメータ名の昇順でソートされていないといけないためソート
ksort($param_array);

// シグネチャ作成用にパラメータの文字列を生成
// oauth_consumer_key=XXXXXXXXX&oauth_nonce=xxxxx...のようなパラメータ文字列を生成
$param = "";
foreach ($param_array as $key => $value) {
	if($param != "") $param .="&";
	$param .= $key . "=" . $value;
}

// シグネチャの生成
// 「HTTPのメソッド名&URLエンコードされたAPIのURL&URLエンコードされた昇順に並べたパラメータ文字列」を作ります
$signature_param = "GET&" . urlencode($api_url) . "&" . urlencode($param);

// SHA1ハッシュを取得し、BASE64エンコードします。
// これでoauth_signatureの値が完成です。
$oauth_signature = base64_encode(hash_hmac("sha1", $signature_param, urlencode($oauth_consumer_secret) . "&", true));

非常に面倒な手続きですが、twitterのAPI呼び出しでは、ほとんどのAPIでパラメータ文字列のシグネチャを生成する必要があるので内容をしっかり把握しておくといいと思います。

応答

前述で生成したシグネチャとパラメータを設定してAPI URLにアクセスすると、処理が正常に行われた場合、

oauth_token=トークン&oauth_token_secret=トークンシークレット

という形でリクエストトークンが取得できます。次はこのリクエストトークンを使ってアクセストークンを取得します。

アクセストークンを取得するには、リクエストトークンを使って、ユーザにアクセス許可を求めるためのURLを生成し、そのURLにリダイレクトする必要があります。

リダイレクト後、ユーザが許可ボタンを押すと、開発者登録で設定したcallback URLに処理がリダイレクトされ、アクセストークンの取得が行われます。

とりあえず、ここでは、「アクセストークンを取得するために、リクエストトークンを使って、ユーザにアクセス許可を求めるためのURLを生成する」処理までのサンプルを載せます。本来はこのURLに自動的にリダイレクトするのが望ましいですが、分かりやすくするため、URLのリンクとして表示するサンプルになっています。

/**
 * リクエストトークン取得サンプル
 */

// 開発者情報設定
$oauth_consumer_key = "xxxxxxxxxxxxxxxxxxxx";
$oauth_consumer_secret = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";

// API URL
$api_url = "http://twitter.com/oauth/request_token";

// 必要なパラメータを設定
$param_array = array();
$param_array["oauth_consumer_key"] = $oauth_consumer_key;		// twitterで取得したConsumer key
$param_array["oauth_nonce"] = md5(uniqid(rand(), true));		// ランダムな英数字のみからなる文字列32文字を設定
$param_array["oauth_signature_method"] = "HMAC-SHA1";			// HMAC-SHA1固定
$param_array["oauth_timestamp"] = mktime();						// いわゆるUNIXタイムスタンプ
$param_array["oauth_version"] = "1.0";							// 1.0固定

// パラメータ名でソートされていないといけないためソート
ksort($param_array);

// シグネチャ作成用にパラメータを生成
$param = "";
foreach ($param_array as $key => $value) {
	if($param != "") $param .="&";
	$param .= $key . "=" . $value;
}

// シグネチャの生成
$signature_param = "GET&" . urlencode($api_url) . "&" . urlencode($param);
$oauth_signature = base64_encode(hash_hmac("sha1", $signature_param, urlencode($oauth_consumer_secret) . "&", true));

// シグネチャの設定
$param_array["oauth_signature"] = $oauth_signature;				// シグネチャを設定

// 再度パラメータ名でソート
ksort($param_array);

// トークン取得用パラメータを生成
$param = "";
foreach ($param_array as $key => $value) {
	if($param != "") $param .= "&";
	$param .= $key . "=" . $value;
}

// アクセスURL生成
$url = $api_url . "?" . $param;

// curl初期化
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);// 文字列として取得する設定

// トークンの取得
$response = curl_exec($ch);

// curl終了
curl_close($ch);

// トークンをセッションに設定
session_start();
$token_array = explode("&", $response);
$token = explode("=", $token_array[0]);
$oauth_token = $token[1];
$token = explode("=", $token_array[1]);
$oauth_token_secret = $token[1];

$_SESSION["oauth_token"] = $oauth_token;
$_SESSION["oauth_token_secret"] = $oauth_token_secret;

// 取得したリクエストトークンを使ってtwitterにアクエスする
// 下記URLにアクセスし、許可ボタンを押下すると、開発者登録でしていした
// callback URLにリダイレクトが行われる
print("<a href=\"http://api.twitter.com/oauth/authorize?oauth_token={$oauth_token}\">http://api.twitter.com/oauth/authorize?oauth_token={$oauth_token}</a>");

アクセストークンの取得

次にアクセストークンの取得です。前述のサンプルを実行し、最後に表示されるリンクをクリックすると、twitterの画面に飛んでアカウントの利用許可画面が表示されます。

そこで、許可ボタンを押すと、開発者画面で登録してあるcallback URLにoauth_verifierというパラメータ付きでリダイレクトが行われます。callback URLの処理内では、このoauth_verifierの値を使ってアクセストークンを取得することとなります。

まず、アクセストークン取得のAPIの説明を見てみます。

API URL:

  • URL
    http://api.twitter.com/oauth/access_token

引数:

  • oauth_consumer_key (必須)
    アプリケーションの consumer key
  • oauth_nonce (必須)
    ランダムな適当な長さの文字列。使用可能な文字は ASCII コードの 0x21 〜 0x7F の範囲内で printable なもの
  • oauth_signature_method (必須)
    署名方式。Twitter では常に HMAC-SHA1 を指定する
  • oauth_timestamp (必須)
    本リクエストを実行するための処理を開始した日時
  • oauth_token
    リクエストトークン取得時に取得したoauth_tokenの値
  • oauth_verifier
    パラメータとして渡されたoauth_verifierの値
  • oauth_version (オプション)
    適用する OAuth のバージョン。Twitter では常に 1.0 を指定する
  • oauth_signature (必須)
    上記パラメータ(oauth_consumer_key ? oauth_version)等を元に生成した文字列を、「アプリケーションの consumer secret(を URL エンコードしたもの)」を暗号鍵として HMAC-SHA1 方式で生成した署名を BASE64 エンコードしたもの

メソッド:

  • POST

応答:

  • 認証に成功すると、以下のような文字列が返る
    oauth_token=トークン&oauth_token_secret=トークンシークレット&user_id=ユーザID&screen_name=スクリーン名

ほとんどのパラメータはリクエストトークンの取得時と同じです。今回新たに加わったパラメータについて説明します。

oauth_token

リクエストトークンの取得時に取得したトークンです。サンプルではセッションに入れていますので、その値を取得して使用できます。

session_start();
$oauth_token = $_SESSION["oauth_token"];

oauth_verifier

callback URLにリダイレクトされる際に付加されたURLパラメータから取得します。

$oauth_verifier = $_REQUEST["oauth_verifier "];

oauth_signature

この値も基本的にはリクエストトークン取得時の処理と同じです。
oauth_consumer_key〜oauth_versionまでのパラメータの値をパラメータ名の昇順に並べて、

HTTPのメソッド名&URLエンコードされたAPIのURL&URLエンコードされた昇順に並べたパラメータ文字列

という文字列を生成し、それのSHA1ハッシュを取得し、さらにBASE64エンコードした値となります。
注意点としては、今回はHTTPのメソッドがPOSTになっているぐらいです。

応答

前述で生成したシグネチャとパラメータを設定してAPI URLにアクセスすると、処理が正常に行われた場合、

oauth_token=トークン&oauth_token_secret=トークンシークレット&user_id=ユーザID&screen_name=スクリーン名

という形でアクセストークンとユーザの情報が取得できます。後はこのアクセストークンを使って様々なtwitterのAPIを利用することができます。

ここでは、アクセストークンの取得までのサンプルを掲載します。

/**
 * アクセストークン取得サンプル
 * この処理はtwitterからリダイレクトされて呼ばれる
 * このPHP自体のURLを開発者登録の画面でcallback URLとして設定しておく必要がある
 */

// 開発者情報設定
$oauth_consumer_key = "xxxxxxxxxxxxxxxxxxxx";
$oauth_consumer_secret = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";

// API URL
$api_url = "http://twitter.com/oauth/access_token";

// リクエストトークンをセッションより取得
session_start();
$oauth_token = $_SESSION["oauth_token"];
$oauth_token_secret = $_SESSION["oauth_token_secret"];

// oauth_verifierの取得
$oauth_verifier = $_REQUEST["oauth_verifier "];

// 必要なパラメータを設定
$param_array = array();
$param_array["oauth_consumer_key"] = $oauth_consumer_key;		// twitterで取得したConsumer key
$param_array["oauth_nonce"] = md5(uniqid(rand(), true));		// ランダムな英数字のみからなる文字列32文字を設定
$param_array["oauth_signature_method"] = "HMAC-SHA1";			// HMAC-SHA1固定
$param_array["oauth_timestamp"] = mktime();				// いわゆるUNIXタイムスタンプ
$param_array["oauth_token"] = $oauth_token;				// 取得済のリクエストトークン
$param_array["oauth_verifier"] = $oauth_verifier;			// 取得したoauth_verifier
$param_array["oauth_version"] = "1.0";					// 1.0固定

// パラメータ名でソートされていないといけないためソート
ksort($param_array);

// シグネチャ作成用にパラメータを生成
$param = "";
foreach ($param_array as $key => $value) {
	if($param != "") $param .="&";
	$param .= $key . "=" . $value;
}

// シグネチャの生成
$signature_param = "GET&" . urlencode($api_url) . "&" . urlencode($param);
$oauth_signature = base64_encode(hash_hmac("sha1", $signature_param, urlencode($oauth_consumer_secret) . "&", true));

// シグネチャの設定
$param_array["oauth_signature"] = $oauth_signature;				// シグネチャを設定

// 再度パラメータ名でソート
ksort($param_array);

// トークン取得用パラメータを生成
$param = "";
foreach ($param_array as $key => $value) {
	if($param != "") $param .= "&";
	$param .= $key . "=" . $value;
}


// アクセスURL生成
$url = $api_url;

// curl初期化
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ($ch,CURLOPT_POST, true);// POSTでアクセス
curl_setopt ($ch,CURLOPT_POSTFIELDS, $param);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);// 文字列として取得する設定

// トークンの取得
$response = curl_exec($ch);

// curl終了
curl_close($ch);

// アクセストークンの表示
print($response);

本来、アクセストークンを取得した後につぶやき投稿処理等のサンプルを載せようと思ったのですが、だいぶ説明が長くなってしまったので、とりあえず、そこら辺はまたの機会にしたいと思います。

まぁ、twitter用のPHP関連ライブラリもいろいろ出ていますので、わざわざライブラリを使わないで書く必要はあんまりないんですけど、ライセンスの問題やいろいろと自分で書いてみたいって人のためにサンプルとして載せておきます。

なお、例によって、サンプルプログラムは自由に使っていただいてOKです。無保証ですので、不具合等あったらがんばって直してみてくださいw

とりあえず、そんなとこで技術メモでした。

————————————————————–
2011-09-21
PHPでライブラリを使わずにtwitterのOAuth認証を行うサンプル(つぶやき投稿編)も書きましたので、合わせてどうぞ。

Twitterでも情報配信中!



コメント(1)


katzee

初めまして、OAuth認証でTwitterにアクセスしたいがためこのサイトにたどり着きました。
ライブラリを使わない解説が大変分かり易いです。

一つ疑問点としてアクセストークンの取得が3回に1回ぐらいしか成功しません。

// トークンの取得
$response = curl_exec($ch);
で $response が成功するときと「Failed to validate oauth signature and tokenmiss」が出るときがあるんですよね。
連投によるTwitter側の規制ではない気がします。

数回に一度は成功するため、対処に困っております(^^;


コメントを残す

メールアドレスが公開されることはありません。



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

※コメントは承認制です。承認されるまで表示されません。