今回は以前構築したセマンティック・メディアウィキ (Semantic Media Wiki, SMW、SMW+) に OpenID でログインできるように OpenID extension をインストール。
MediaWikiのバージョンは1.15.3。これに必要なOpenID extensionのバージョンは0.8.2らしい (DownloadページでMediaWikiのバージョンを指定すると自動的に適切なパッケージが得られる)。
これに必要な PHP ライブラリはOpenID Enabledなんだが、それが必要とするライブラリがいろいろとあり、その準備から始める必要があった。
OpenID Enabled
まず、OpenID EnabledのパッケージであるPHP-OpenIDを取得して展開。
そこで得られるドキュメント(README)を読む。
すると最初に必要なのはGMP (GNU Multiple Precision)。
早速GMPライブラリを構築してインストール。
普通に ./configure; make; make check としてOK。最後の make check を忘れずに。
続いて必要なのはClient URL Library。
GMP同様、cURLライブラリを構築してインストール。
GMPとcURLが準備出来たら、configure に --with-gmp --with-curl
を追加してPHPを再構築。
そしてPHP構築時に作られる pear コマンドを用いて、データベースの準備を行う。
# pear install DB
更に、DOMライブラリが必要だが、これはPHPコアに含まれているので特に作業をする必要は無い。
以上までの作業が終わったら、PHP-OpenIDパッケージの展開ディレクトリ直下にあるAuthディレクトリをPHPのライブラリパス(例えば /usr/local/lib/php以下)にコピーして終了。
OpenID extension
そしていよいよMediaWiki拡張(プラグイン)のインストール。
その他多くのそれと同様にパッケージをダウンロードしたら、extension以下に展開し、ドキュメント(README)を読む。
まずは必要なデータベーステーブルを用意。
mysql -h yourdbhost -u youradminuser -p yourwikidb < openid_table.sql
後は、また、その他大勢と同様に LocalSettings.php に以下の1行を追加。
require_once("$IP/extensions/OpenID/OpenID.setup.php");
本プラグインの場合は、OpenIDのTrustRootを設定するために、以下の1行も必要な場合が多い。
$wgTrustRoot = "http://example.com/mw/index.php";
以上で全て終了!!
アクセスしてみると「OpenIDでログイン」の文字。めでたし、めでたし。
早速ログイン!
OpenIDプロバイダにリダイレクトされ、認証が済み、元のサイトにリダイレクトされた。
今回はすんなり作業が終わったかにみえた。
しかし、そうはならないのが世の常。
特に、非英語環境ではね。
バグ発覚!
なんと元サイトにリダイレクトされると、エラーが表示される。
Invalid openid.mode '<No mode set>'
なんだこれは?
調べてみると、OpenIDプロバイダにリダイレクトする際に引数として含める戻りアドレス(URL)と、Media Wiki側 (relying party) でログインユーザを検証する際のそれが異なっていることが判明。
何故、そんなことが起こるのか?
それは、プロバイダにリダイレクトする時には英語の引数「OpenIDFinish」がタイトルに続くコロンの後に追加されるのだが、プロバイダから逆にリダイレクトされてきた時には、URLに含まれる、プロバイダから得られた引数を検証する前に、日本語のページ(「OpenIDFinish」の部分が「OpenID完了」となっている)にリダイレクトされてしまうから。
そして検証する際には上述の通りプロバイダに与えた戻りアドレスと実際に検証を行うそれに相違があることとなり、上記のエラーが表示される。
英語環境でしかテストをしていなかったのでしょうね。
具体的には SpecialOpenID.body.php の228行目にある
function login($openid_url, $finish_page = 'OpenIDFinish') {
が原因。
応急処置として現在の環境、つまり日本語環境で少なくとも動作するように英語環境と同じ手法を用いて問題を回避。
function login($openid_url, $finish_page = 'OpenID完了') {
無事、OpenIDによるログインが可能になった。
そしてバグレポートをBugzillaに送付。
OpenID完了!