公開した。
Openpearでパッケージを公開するとメールアドレスも公開されるという事をさっき知った。
もういいやと思って、文中のPear準拠のコメント部分で本名も晒した。
プログラムは去年書いたものをベースにしたんだけど、結構書き方も変わった。
なかなかいい感じの書き方が出来たんじゃないかと思ってる。
HTTP_OAuthProvider - Openpear
http://openpear.org/package/HTTP_OAuthProvider
/HTTP_OAuthProvider/trunk - リポジトリブラウザ - Openpear
http://openpear.org/repository/HTTP_OAuthProvider/trunk
機能
OAuthリクエストの認証を行うサービスプロバイダ側のライブラリ。
2Legged OAuthと3Legged OAuthの両方に対応。
対応しているシグネチャ方式は、HMAC-SHA1とRSA-SHA1。
トークンの保持に、Cache_Liteを使用。
トークン保持の方法は今後いくつか増やす予定。
インストール
Openpearのチャンネル追加。
[root@localhost ~]# pear channel-discover openpear.org Adding Channel "openpear.org" succeeded Discovery of channel "openpear.org" succeeded
HTTP_OAuthProviderのインストール。
[root@localhost ~]# pear install openpear/HTTP_OAuthProvider downloading HTTP_OAuthProvider-1.0.0.tgz ... Starting to download HTTP_OAuthProvider-1.0.0.tgz (6,719 bytes) .....done: 6,719 bytes install ok: channel://openpear.org/HTTP_OAuthProvider-1.0.0
サンプル
現時点でここに書いてあるものと同じだけど…。
/HTTP_OAuthProvider/trunk/example - リポジトリブラウザ - Openpear
http://openpear.org/repository/HTTP_OAuthProvider/trunk/example
2Legged OAuth認証を行う
<?php require_once('HTTP/OAuthProvider.php'); require_once('config.php'); $o = new HTTP_OAuthProvider(); try { $o->setFetchConsumerHandler('fetchConsumer'); $o->authenticate(); echo "Auth OK!!!\n"; printf("consumer: %s\n", $o->getConsumer()->getKey()); } catch(Exception $e) { header(sprintf('HTTP/1.0 %d', $e->getCode())); echo $e->getMessage(); }
リクエストトークンを発行する
<?php require_once('HTTP/OAuthProvider.php'); require_once('config.php'); $o = new HTTP_OAuthProvider(); try { $o->setFetchConsumerHandler('fetchConsumer'); echo $o->issueRequestToken(); } catch(Exception $e) { header(sprintf('HTTP/1.0 %d', $e->getCode())); echo $e->getMessage(); }
ユーザの認可を保存する(フォームも表示)
<?php require_once('HTTP/OAuthProvider.php'); require_once('config.php'); $content = "<b>this is provider's page !!</b><br />\n"; $o = new HTTP_OAuthProvider(); try { $o->setFetchConsumerHandler('fetchConsumer'); // check request token if (!$o->existsRequestToken()) { throw new Exception('not found request token', 200); } // show callback url if (isset($_REQUEST['authorize_confirm'])) { if ($_REQUEST['authorize_confirm']) { $callback = $o->authorizeToken($user_id, true); $content .= "you choose agree<br />\n"; } else { $callback = $o->authorizeToken($user_id, false); $content .= "you choose disagree<br />\n"; } $content .= "return to consumer's page<br />\n"; $content .= sprintf('<a href="%s">%s</a>', $callback, $callback)."<br />\n"; // show form } else { $content .= sprintf("hello. user id %s !<br />\n", $user_id); $content .= "do you authorize the consumer?<br />\n"; $content .= sprintf("consumer is %s<br />\n", $o->getConsumer()->getKey()); // agree form $content .= '<form action="?" method="post">'."\n"; $content .= sprintf('<input type="hidden" name="oauth_token" value="%s" />', $_REQUEST['oauth_token'])."\n"; $content .= '<input type="hidden" name="authorize_confirm" value="1" />'."\n"; $content .= sprintf('<input type="submit" value="agree">')."\n"; $content .= "</form>\n"; // disagree form $content .= '<form action="?" method="post">'."\n"; $content .= sprintf('<input type="hidden" name="oauth_token" value="%s" />', $_REQUEST['oauth_token'])."\n"; $content .= '<input type="hidden" name="authorize_confirm" value="0" />'."\n"; $content .= sprintf('<input type="submit" value="disagree">')."\n"; $content .= "</form>\n"; } } catch(Exception $e) { header(sprintf('HTTP/1.0 %d', $e->getCode())); $content .= $e->getMessage(); } ?> <html> <head> <title>provider's page</title> </head> <body> <?php echo $content; ?> </body> <html>
認可されたリクエストトークンをアクセストークンに交換する
<?php require_once('HTTP/OAuthProvider.php'); require_once('config.php'); $o = new HTTP_OAuthProvider(); try { $o->setFetchConsumerHandler('fetchConsumer'); echo $o->exchangeAccessToken(); } catch(Exception $e) { header(sprintf('HTTP/1.0 %d', $e->getCode())); echo $e->getMessage(); }
保護されたリソースへのアクセスの認証を行う
<?php require_once('HTTP/OAuthProvider.php'); require_once('config.php'); $o = new HTTP_OAuthProvider(); try { $o->setFetchConsumerHandler('fetchConsumer'); $o->authenticate3L(); echo "this is provider's protected resource !!\n"; printf("consumer: %s\n", $o->getConsumer()->getKey()); printf("user_id: %s\n", $o->getStore()->getUserID()); } catch(Exception $e) { header(sprintf('HTTP/1.0 %d', $e->getCode())); echo $e->getMessage(); }
設定ファイル
コンシューマもユーザも固定。
コンシューマは1人だけいる想定。
ユーザはID12345がログイン済みという想定。
<?php // consumer function fetchConsumer($consumer_key) { $row = array( 'id' => 1, 'key' => 'testconsumer', 'secret' => 'testpass', 'publickey' => null ); if ($consumer_key==$row['key']) { $consumer = new HTTP_OAuthProvider_Consumer($row); return $consumer; } } // user $user_id = 12345;
テスト用コンシューマ
<?php // require HTTP_OAuth require_once('HTTP/OAuth/Consumer.php'); /* 認証情報を格納するためにセッションを開始 */ session_start(); /* Consumer key */ $consumer_key = 'testconsumer'; /* Consumer Secret */ $consumer_secret = 'testpass'; /* プロバイダからの Callback url */ $callback_url = sprintf('http://%s%s', $_SERVER['HTTP_HOST'], $_SERVER['SCRIPT_NAME']); $provider_base = 'http://example.com/example/'; $request_url = $provider_base.'3legged_request.php'; $authorize_url = $provider_base.'3legged_authorize.php'; $access_url = $provider_base.'3legged_access.php'; $resource_url = $provider_base.'3legged_resource.php'; /* Set up placeholder */ $content = ''; /* セッションのクリア */ if (@$_REQUEST['test'] === 'clear') { session_destroy(); session_start(); } try { // -- init HTTP_OAuth_Consumer $oauth = new HTTP_OAuth_Consumer($consumer_key, $consumer_secret); // ssl通信を可能に $http_request = new HTTP_Request2(); $http_request->setConfig('ssl_verify_peer', false); $consumer_request = new HTTP_OAuth_Consumer_Request; $consumer_request->accept($http_request); $oauth->accept($consumer_request); if (!empty($_REQUEST['oauth_token']) && $_SESSION['oauth_state'] === 'start') { // -- プロバイダから認証後に戻ってきた場合 (callback処理) $_SESSION['oauth_state'] = 'returned'; if (empty($_SESSION['oauth_access_token']) || empty($_SESSION['oauth_access_token_secret'])) { // -- access_tokenが未取得の場合 /* request tokenをセット */ $oauth->setToken($_SESSION['oauth_request_token']); $oauth->setTokenSecret($_SESSION['oauth_request_token_secret']); /* プロバイダから戻ってきた oauth_verifierをセット */ $oauth_verifier = $_REQUEST['oauth_verifier']; /* Access token をリクエスト */ $oauth->getAccessToken($access_url, $oauth_verifier); /* Acces tokenを保存 (実際のアプリケーションではこれをDB等に保存しておきます。) */ $_SESSION['oauth_access_token'] = $oauth->getToken(); $_SESSION['oauth_access_token_secret'] = $oauth->getTokenSecret(); } } if (!empty($_SESSION['oauth_access_token']) && !empty($_SESSION['oauth_access_token_secret'])) { // -- 認証済みの場合 /* access_tokenをセット */ $oauth->setToken($_SESSION['oauth_access_token']); $oauth->setTokenSecret($_SESSION['oauth_access_token_secret']); /* ユーザ情報を取得するリクエストを発行. */ $result = $oauth->sendRequest($resource_url, array(), 'GET'); /* データを取得 */ $content = $result->getBody(); } else { // -- 初回呼び出し時 /* プロバイダからrequest_tokenの取得 */ $oauth->getRequestToken($request_url, $callback_url); /* tokenをセッションに保存 */ $_SESSION['oauth_request_token'] = $oauth->getToken(); $_SESSION['oauth_request_token_secret'] = $oauth->getTokenSecret(); /* ステータスをstartにセット */ $_SESSION['oauth_state'] = "start"; /* authorization URL を取得 */ $request_link = $oauth->getAuthorizeURL($authorize_url); /* authorization URLのリンクを作成 */ $content = 'Click on the link to go to provider to authorize your account.'; $content .= '<br /><a href="'.$request_link.'">'.$request_link.'</a>'; } } catch (Exception $e) { $content = $e->getMessage(); } ?> <html> <head> <title>OAuth in PHP</title> </head> <body> <h2>Welcome to a OAuth PHP example.</h2> <p><a href='<?php echo $_SERVER['PHP_SELF']; ?>?test=clear'>clear sessions</a></p> <p><pre><?php print_r($content); ?><pre></p> </body> </html>
3Legged OAuthのコンシューマ側のサンプルは、ここから拝借した。
HTTP_OAuthを利用してTwitterのOAuth認証を行う @ php-tips
http://php-tips.com/php/2009/11/http_oauth%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%A6twitter%E3%81%AEoauth%E8%AA%8D%E8%A8%BC%E3%82%92%E8%A1%8C%E3%81%86
OAuthの仕様がよく解らない人用URL
OAuthプロトコルの中身をざっくり解説してみるよ - ゆろよろ日記
http://d.hatena.ne.jp/yuroyoro/20100506/1273137673
PHPを読んだことある人のためのOAuthのSignature解説 - r-weblife
http://d.hatena.ne.jp/ritou/20090912/1252776563
OpenSocialのサービスプロバイダっぽいのを作ってみる 5.OAuth Core 1.0a(3legged OAuth)の仕様 - eth0jpの日記
http://d.hatena.ne.jp/eth0jp/20090826/1251228344
OpenSocialのサービスプロバイダっぽいのを作ってみる 6.OAuth Core 1.0a(3legged OAuth)を実装してみた - eth0jpの日記
http://d.hatena.ne.jp/eth0jp/20090829/1251497285
「OAuth Core 1.0 Revision A」日本語訳をつくってみた - tzmtkのブログ
http://d.hatena.ne.jp/tzmtk/20090723/p1
OAuth Core 1.0a
http://oauth.net/core/1.0a/