Catalystでmixi OpenIDからニックネームを取得
ボヤボヤしてるうちにmixiがOpenIDのProviderになって、そろそろOpenIDのRPに対応する準備しとかんとあかんやろ、と思い、認証してニックネームを取得してくるだけのRPのテストプログラムを作ってみた。
ここで紹介されているサンプルのCatalyst版(の更にマイミク認証を除いたやつ)です。
Catalystは当然インストールしてあるとして、事前にNet::OpenID::ConsumerとCatalyst::Authentication::Credential::OpenIDの2つのモジュールをCPANに上がっているやつじゃなくてSubversionのリポジトリから取得してそれぞれインストールします。
Net::OpenID::Consumerの方は依存モジュールに注意した方が良いみたいなので、以下のページを参考に先に他のモジュールや外部ライブラリをインストールしておく。
$ svn co http://code.sixapart.com/svn/openid/trunk/perl/Net-OpenID-Consumer/ $ perl Makefile.PL $ make $ make install
$ svn co http://svn.coderepos.org/share/lang/perl/Catalyst-Authentication-Credential-OpenID/trunk/ Catalyst-Authentic ation-Credential-OpenID $ perl Makefile.PL $ make $ make install
自分の環境ではもう一つハマリどころがあって、Net::OpenID::Consumer(正確に言うと同梱されているNet::OpenID::Yadis)がXML::Simpleを使用しているんだけどMakefileのPREREQ_PMに書いてないのでインストール要求されなかったこと。呼び出し側のCatalyst::Authentication::Credential::OpenIDの方でコンパイルエラーが起きていたので原因を特定するのに時間がかかってしまった。なので、手元の環境にXML::Simpleを入れてない人は別途インストールする必要があります。
この2つのモジュールを入れてしまえば、あとはcatalyst.pl MyAppしてMyApp.ymlとMyApp.pmとRoot.pmを以下の例の様に書き換えればOK。
MyApp.yml
--- name: MyApp Log::Dispatch: - class: File name: file filename: __path_to(test.log)__ mode: append min_level: debug format: '%P [%p] %m %n' - class: Screen name: screen min_level: debug stderr: 1 format: '[%p] %m%n' Plugin::Authentication: default_realm: openid realms: openid: credential: class: OpenID extension_args: 'http://openid.net/extensions/sreg/1.1': required: nickname
MyApp.pm
package MyApp; use strict; use warnings; use Catalyst::Runtime '5.70'; use Catalyst qw( ConfigLoader Static::Simple Log::Dispatch Authentication Session Session::Store::FastMmap Session::State::Cookie ); our $VERSION = '0.01'; __PACKAGE__->config( name => 'MyApp' ); # Start the application __PACKAGE__->setup; 1;
Root.pm
package MyApp::Controller::Root; use strict; use warnings; use base 'Catalyst::Controller'; __PACKAGE__->config->{namespace} = ''; sub default : Private { my ($self, $c) = @_; $c->log->debug('### default start'); my $template = << "TEMPLATE" <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>mixi OpenID Login Test</title> </head> <body> <h1>mixi OpenID Login Test</h1> ボタンをクリック!<a href="/login?openid_identifier=https://mixi.jp"><img src="/static/images/b_150.gif" alt="mixiでログイン" border="0"></a> TEMPLATE ; $c->res->body($template); $c->log->debug('### default end'); } sub login : Local { my ($self, $c) = @_; $c->log->debug('### login start'); if ($c->authenticate) { $c->log->debug('### authenticated!'); # success my $id = $c->user->{url}; my $nickname = $c->user->{display}; my $template = << "TEMPLATE" <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>mixi OpenID Login Test SUCCESS!</title> </head> <body> <h1>mixi OpenID Login Test</h1> ログインに成功しました!<br> こんにちは、$nickname ( $id ) さん TEMPLATE ; $c->res->body($template); } elsif ($c->res->redirect) { $c->log->debug('### redirect'); # redirect to OP/IdP, nothing to do } else { # error $c->log->debug('### error!'); my $template = << "TEMPLATE" <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>mixi OpenID Login Test ERROR!</title> </head> <body> <h1>mixi OpenID Login Test</h1> ログインに失敗しました。 TEMPLATE ; $c->res->status(401); $c->res->body($template); } $c->log->debug('### login end'); } sub end : ActionClass('RenderView') {} 1;
認証成功後は、$c->user->{url}でユーザのIdentifierが、(extention_argsにsregでnicknameを要求していれば)$c->user-{display}にニックネームが取得できます。今回はmixiからニックネームを持ってこれるか試したかったので手抜きでhttps://mixi.jpを直書きしたけど、Claimed Identifier(Root.pmのopenid_identifierの部分)を入力できるようにすれば他のOpenID Providerにも対応できるはず。試してないけど。