OpenIDファーストプロトタイプを作ろう
サンプルコードを使って簡単なプロトタイプを作ろう
これまで、OpenIDの背景や攻撃の種類や対処の仕組みについて簡単に見てきましたが、第4回では、サンプルコードを使って簡単なプロトタイプを作ってみましょう。
Web上でOpenIDの実装方法を紹介した記事を見つけることができますので、詳細はそちらを参考にしていただき、本連載ではサンプルコードを元にどれだけ簡単に試すことができるかを追及してみたいと思います。特に今回は、PR(ユーザーが利用したいサービス)の立場でYahoo!JapanのOpenIDを利用した認証システムを作ってみます。
なお、前提として先にYahoo!JapanのでOpenIDを登録しておきましょう。
サンプルコードをインストールする
ライブラリは、一般的によく使われているPHP OpenID Libraryを使ってみます。以下のサイトから最新のライブラリをダウンロードしましょう。
http://www.openidenabled.com/php-openid/
筆者は原稿執筆時点(2009年2月現在)で最新版のphp-openid-2.1.2.zipをダウンロードしました。解凍すると複数のディレクトリが展開されますが、まずはサンプルファイルを動かしてみたいのでexamplesディレクトリの中のconsumerディレクトリを開きます。consumerディレクトリにはPRに必要なサンプルコードが入っています(図1-1)。
php-openid-2.1.2/examples/consumer
ディレクトリの中にあるREADMEファイルを読めば設定の仕方がわかります。内容はとてもシンプルで、ポイントは3つです。
1つ目がphp.iniでphpを動作させるディレクトリに制限をしているのであれば、/tmpがそのディレクトリに含まれるようにすることです。これは、認証プロセスの中で/tmpにファイルを作って必要な情報などを書き込むためです。
2つ目がexamplesディレクトリの中にあるconsumer以下のディレクトリをサーバーのドキュメントルート以下にコピーするか、シンボリックリンクを作ることです。
3つ目がconsumerディレクトリだけを使う場合には、AuthディレクトリがPHPのinclude pathに入っていることを確認することです。
つまり、「PHPで/tmpが使えるようにしておく」「consumerディレクトリをコピーしてドキュメントルート以下に置く」「PHPのinclude pathにAuthディレクトリを含める」という3ステップで使えるようになります。
筆者の場合は、php.iniでphpの使えるディレクトリの制限をしていなかったので、単純にphp-openid-2.1.2をコピーして、ドキュメントルートに置いてopenidとリネームしました。もし同じように設定する場合は、以下のURLで確認することができます。
"http://yourhost/openid/examples/consumer/"
では、ファイルの構成について簡単に説明しましょう。consumerディレクトリの中には、index.php、try_auth.php、finish_auth.php、common.phpの4つのファイルが入っています。後ほど詳細に見ていきますが、簡単に説明しましょう。
まず、index.phpは認証の受付ページで、エンドユーザーの入力画面になります。try_auth.phpは、認証の受付とOPとのやりとりし、エンドユーザーをOP(OpenID発行サイト)にリダイレクトをするためのファイルです。finish_auth.phpは、OPからの認証後に、OPからのレスポンスをチェックして次につなげるためのファイルです。common.phpは、そのほかAuth以下のファイルに書かれている種々の認証処理を呼び出したり、設定するための共通ファイルです。これらのファイルの関係を図1-2に示します。
準備が整ったら、次のページに進み、実際にアクセスして動きを確認してみましょう。
実際に動きを確認してみる
アクセスしてみると、入力フォームが表示されると思います。ページの下にPAPE policiesとあります。これは、PRがOPにリクエストする認証ポシリーですが、ここではいったんそのままにしておきましょう。
次に、Identity URLの部分に「yahoo.co.jp」と入力して送信ボタンを押すと、既にyahooでopenidを作っていたので、リダイレクトバックする自分のサービスのURLなどを確認するための画面が出てきます。そこで「続ける」ボタンをクリックすると、認証の成功メッセージが表示されます(図2)。「mixi.jp」と入力した場合にも同様です。
なお認証の成功画面のURLをコピーしてみると、以下のように非常に長いURLになっています。
http://yourhost/openid/examples/consumer/finish_auth.php?janrain_nonce=2009-02-05T04%3A14%3A42ZQ5.......................................
レスポンスのデータが書き込まれていますが、URLをコピーして別のタブなどで見てみると、以下のメッセージが出てきて認証が通りません。
OpenID authentication failed: Nonce already used or out of range
これは第3回で説明したNonce(ノンス)が使われているというメッセージです。
ここまで、サンプルコードの導入について非常に簡単に書きました。やってみると、ローカルからアクセスしても認証されない、あるいはAuthに対するinclude pathが通っていないためにプログラムが動かない、といった問題が出てくるかもしれませんが、その場合はプログラムよりも実行環境に問題がある場合が多いので、再度確認してみてください。
ファーストプロトタイプを作ってみる
動いたところで一安心ですが、次に、このサンプルコードを少しカスタマイズしながら簡単にファーストプロトタイプを作ってみましょう。第1回で、OpenID 2.0になってからは、ユーザーはyahoo.co.jpといったOpenIDを発行するサイトのアドレスを入力する、あるいはサイトに設置したボタンをクリックすれば認証できるようになったことを説明しました。まずは、実際にボタンを使って認証プロセスをスタートしてみましょう。
まずは、以下のサイトからYahoo!Japanのボタンを取得します。
http://developer.yahoo.co.jp/other/openid/loginbuttons.html
認証の受付ページは、index.phpですから、フォームの代わりに取得したボタンにURLをつけてtry_auth.phpにアクセスさせます。いろいろなコードの書き方はあると思いますが、簡単に以下のようにしてみます。
これで、try_auth.phpが呼び出されます。続いてtry_auth.phpを見てみましょう。
try_auth.phpとcommon.php
try_auth.phpの基本となるファクションは、run()です。とてもシンプルに書かれており、機能としては図3-1のようになります。つまり「openid_identifierを取得して、いくつかリクエストを追加して、リダイレクトをする」といった基本的な動きが記述されています。それ以外のエラー処理ももちろん入っています。
すぐにわかると思いますが、ディスカバリーや第3回で説明したアソシエーションといったコアな機能は、try_auth.phpの中には書かれておらず、Auth以下のファイルに入っています。今回はAuth以下の説明は割愛します。
なお、Auth以下のファイルをカスタマイズする場合、デフォルトではエラーメッセージがすべて英語になるため、日本語に変更したり、sregやpapeなどの追加リクエストの部分を削除するとよいでしょう。
次に、common.phpを見てみます。
ファイルの前半のdoIncludes()という機能で、Auth以下のファイルをインクルードしています。中盤の&getStoreという機能で、OpenIDの情報をストアするためのファイルを指定します。デフォルトは以下のようになっています。もしストアする場所を変えたい場合はここをカスタマイズします。もちろんデータベースにストアすることもできます。
$store_path = "/tmp/_php_consumer_test";
最後の2つの機能で、OPからリダイレクトバックされるパスと、Trust Rootを指定します。まず、getReturnTo()ですが、デフォルトで図3-2のようになっています。
通常ポート番号は指定する必要がないためコメントアウトしたり、ファイル名を任意のファイル名に変更します。成功後ページのファイルを別のディレクトリに置いている場合はディレクトリ名も変えます。例として、ポートをコメントアウトして、ファイル名を変更した例を図3-3に示します。
次にTrust Rootですが、これはPRのルートURLです。OpenID 2.0ではRealmという用語が使われています。これも必要に応じてポート番号をコメントアウトします。
finish_auth.php
最後は、finish_auth.phpです。これは、認証が成功した後の処理、成功しない場合の処理が書いてあります。デフォルトでは成功すると下記のようなメッセージが表示されます。
You have successfully verified https://me.yahoo.co.jp/a/SaIt.ggdaZ5IxP0BGRk.rorg3rvNqHLMJZEJ81xY.DoupN-- as your identity.
ここもカスタマイズすれば、メッセージの内容を変更したり、メッセージを日本語化したりすることができます。デフォルトでは、$successという変数にメッセージを追加して、最後にindex.phpをインクルードしてその中でメッセージとしてまとめて表示しています。よって、index.phpではなくて、別のファイルをインクルードすれば成功後の見え方をカスタマイズすることができます。
ここまで、サンプルコードのカスタマイズについて説明しましたが、実際は、新規登録とログインの処理もかかわってきますし、OpenIDを利用しない一般ユーザーのシナリオも考えなければいけません。それについてはまた別の機会で考えたいと思います。
さて、4回にわたってOpenIDの概要について紹介してきましたが、いかがでしたでしょうか。エンジニアでセキュリティーに詳しい方にとっては物足りなかったかもしれませんが、初めての方にも理解してもらいやすいようになるべく平易に書いたつもりです。導入を考えている方は、まずはサンプルコードで遊んで見ることをお勧めします。