perlでOpenID Consumerを実装してみる

OpenID を理解するために、OpenID Consumerをperlで実装してみることにした。といっても、 Net::OpenID::Consumer モジュールを利用しているわけで、いちから自分で実装しているわけではないです。「モジュールがあるから楽勝」と思っていたら、意外とてこずってしまいました。動作サンプルソース

認証時の流れについては、「ぴろ日記 - OpenID: Specs , OpenID認証サーバ , OpenIDにおける認証って奴」が詳しいです。今回実装しているのは、ぴろ日記さんで「とりあえずわかりやすい」と言われている、「dumb + setup モード」です。

以下、簡単に説明を。

動作サンプルにアクセスすると、以下の部分が実行されます。

sub login {
    my $self = shift;

    if($self->query->param('openid.sig')){
    my $csr = $self->_create_csr;
    my $vident = $csr->verified_identity or die $!;
    return 'You are <strong>' . $vident->url . '</strong> !';
    }
    else {
    my $template = $self->load_tmpl('login.html');
    return $template->output;
    }
}

openid.sig パラメータが渡されていると、Open ID Serverに対して認証情報の正当性を確認しに行きますが、まだ最初のアクセスで認証していませんので、else 以下が実行されて、ログインフォームを表示します。

ログインフォームに、自分のIDとなるURLを入力、サブミットすると以下のコードが実行されます。

sub do_login {
    my $self = shift;
    
    my $csr = $self->_create_csr;
    my $claimed_identity = $csr->claimed_identity($self->query->param('openid_url'));
    my $check_url = $claimed_identity->check_url(
                       return_to      => 'http://mizzy.org/openid/',
                       trust_root     => 'http://mizzy.org/',
                       delayed_return => 1,
                         );

    $self->header_type('redirect');
    $self->header_props(-url => $check_url);
    return;
}

sub _create_csr {
    my $self = shift;
    my $csr = Net::OpenID::Consumer->new(
                     args            => $self->query,
                     consumer_secret => '012345',
                     );

    return $csr;
}

ここでは、ぴろ日記さんの説明にある、1), 2)の処理が実行され、OpenID Serverへリダイレクトされます。この処理は、OpenID: Specscheckid_setup にあたります。

OpenID Server上での認証が完了すると、QUERY_STRINGに様々なパラメータをセットした状態で、http://mizzy.org/openid/ へ戻ってき、最初と同様以下のサブルーチンが実行されます。

sub login {
    my $self = shift;

    if($self->query->param('openid.sig')){
    my $csr = $self->_create_csr;
    my $vident = $csr->verified_identity or die $!;
    return 'You are <strong>' . $vident->url . '</strong> !';
    }
    else {
    my $template = $self->load_tmpl('login.html');
    return $template->output;
    }
}

今度はopenid.sigパラメータ(と他のOpenID関連パラメータ)が QUERY_STRINGにより渡されていますので、 $csr->verified_identity を実行して、ぴろ日記さんの説明4)にあたる、認証情報の正当性確認を OpenID Server に対して行います。この処理は、OpenID: Specscheck_authentication にあたります。

正当性が確認できると、「You are あなたのURL !」 と表示されます。

username.videntity.org と livejournal.com/users/username/ はIDとして正常に動作することが確認できましたが、profile.typekey.com/username/ はなぜか openid.mode=cancel となってしまい、認証できません。videntity.org のログインに profile.typekey.com/username/ を利用しても認証できないので、typekey 側の問題なのかなぁ…