at posts/single.html

PHP OpenID を使う (2)

RubyKaigi 2007 の日なのに PHP を使う。

先日の続きで PHP OpenID を使う話。 今日は認証サーバへリダイレクトするときのサンプルコードの中身を見てみよう。 やっていることは、たぶんこんな感じ。

  • ユーザが入力した ID(URL)を受け取る
  • URL から認証サーバを探す
  • OpenID のリクエストを付けて認証サーバへ送る

共通部分 (common.php)

Consumer で使うクラスは以下の2つ。

  • FileStore … Consumer が使うデータ (nonceなど) を格納
  • Consumer … OpenID のクライアント

サンプルコードでは common.php でこのクラスを生成している。

require_once "Auth/OpenID/Consumer.php";
require_once "Auth/OpenID/FileStore.php";

$store_path = "/tmp/_php_consumer_test";
$store = new Auth_OpenID_FileStore($store_path);
$consumer = new Auth_OpenID_Consumer($store);

認証サーバへのリダイレクト (try_auth.php)

エラー処理を省略すると、やっていることは以下の部分になる。

$openid = $_GET['openid_url'];
$auth_request = $consumer->begin($openid);
$auth_request->addExtensionArg('sreg', 'optional', 'email');
$redirect_url = $auth_request->redirectURL($trust_root,
                                           $process_url);

思ったよりもシンプルだった。

  1. $consumer->begin … ユーザが入力したIDから AuthRequest を生成
  2. $auth_request->addExtensionArg … 認証サーバに対して追加の属性 (email) を要求する
  3. $auth_request->redirectURL … 認証サーバへのリダイレクト先を取得する

最後の redirectURL の引数で渡している $trust_root と $process_url は以下のとおり。

$process_url = sprintf("$scheme://%s:%s%s/openid/finish_auth.php",
                       $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'],
                       dirname($_SERVER['PHP_SELF']));

$trust_root = sprintf("$scheme://%s:%s%s",
                      $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'],
                      dirname($_SERVER['PHP_SELF']));

trust_root は現在のディレクトリで、 process_url はそのディレクトリの finish_auth.php になってる。 自分でアプリを作るときは、 trust_root に固定文字列を渡して process_url は動的な文字列を渡すようにするのかな。よく分かってない。 Yet Another Hackadelic - ソースから読むOpenID (1)が参考になりそう。

$auth_request->redirectURL の戻り値に含まれるクエリは以下の通り。

actionopenid&openid
identityhttp%3A%2F%2Fmachu.videntity.org%2F
openid.modecheckid_setup
openid.return_tohttp%3A%2F%2Fwww.machu.jp%3A80%2Fopenid%2Ffinish_auth.php%3Fnonce%3DOX2ioGxj
openid.sreg.optionalemail
openid.trust_roothttp%3A%2F%2Fwww.machu.jp%3A80%2Fopenid

以下のようにLocation を返し、認証サーバへリダイレクトさせる。

header("Location: ".$redirect_url);

認証サーバから認証結果を受け取る (finish_auth.php)

次は認証サーバからの認証結果を受け取るところ。 肝心な箇所だけを抜き出すとこうなる。

$response = $consumer->complete($_GET);
if ($response->status == Auth_OpenID_SUCCESS) {
    $openid = $response->identity_url;
}

認証サーバからの戻り値は、 Auth_OpenID_CANCEL, Auth_OpenID_FAILURE, Auth_OpenID_SUCCESS の3種類があるみたい。 Auth_OpenID_SUCCESS の場合は、 $response->identity_url で利用者の ID が取得できる。 ちなみに、サンプルコードでは、追加の属性(メールアドレスなど)を取得するところも含まれている。 昨日のエラーは、たぶん $consumer->complete で出ているので、あとはライブラリの中を見ていこう。

関連する日記