end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

perlのNet::OpenID::Consumer で OpenID Relying Party (RP)

次のurlの写経。
OpenIDを使ってみよう (1/2):CodeZine(コードジン)
写経して、今更、理解しましたが、厳密にはOpenIDって、Single Sign On (SSO)ではないんですね。
次回は、Net::OpenID::Server を使って、OP (OpenID Provider) を...(まっ、時間があれば)

OpenIDにおける用語(登場人物?)

OP (OpenID Provider) OpenIDによる認証サービスの提供者. 例:yahoo, mixi, google
RP (Relying Party) OpenIDによる認証を受け入れるサイト
Claimed Identifier(url) 利用者のOpenID. 例: https://me.yahoo.co.jp/a/S0uv.R5LVbmpBiXXXX

写経の結果

OpenIDの認証では、OP-RP間で様々なやりとりが行われているので、firebug等で実際にやりとりされるデータも合わせて、見ることもお薦めします。

#!/usr/local/bin/perl
use strict;
use CGI;
use Net::OpenID::Consumer;
#use LWPx::ParanoidAgent;
use LWP::UserAgent;
use Data::Dumper;

main();

sub main {
    my $query = CGI->new;
    $query->charset('utf-8');

    # User-AgentにLWPx::ParanoidAgent を使用する理由は次のurlが分かりやすい.
    # 私の場合、colinux環境でこのOpenID Relying Party を試していますが
    # colinux環境はDNSに登録されていない為か LWPx::ParanoidAgent を使用すると
    # errorになるので、LWP::UserAgent を使用しています
    # http://www.atmarkit.co.jp/ait/articles/0711/20/news128.html
    my $ua = LWP::UserAgent->new;
#    my $ua = LWPx::ParanoidAgent->new();

    my $csr = Net::OpenID::Consumer->new(ua => $ua,
                                         args => $query,
                                         consumer_secret =>sub{$_[0]}); #TODO?

    my $claimed_url = $query->param('openid-url');
    #### step2  userが入力したOpenID(url)を identity provider に認証依頼
    if ($claimed_url) {
        print STDERR "CLAIMED_URL: $claimed_url\n";
        request_to_identity_provider($query,$csr,$claimed_url);
        return;
    }

    if ($query->param('verify')) {
        #### step? http://www.atmarkit.co.jp/ait/articles/0709/21/news142_3.html
        if ($csr->user_cancel) {
            show_login_form($query, 'your login is cancelled.');
            return;
        }

        #### step3 次のurlに記載されている通り。
        # checkid_immediateモードでopenid.user_setup_urlがIdPから返される場合
        # 再びUser-Agentをその指定URLにリダイレクトさせなければならないらしい
        # http://www.atmarkit.co.jp/ait/articles/0709/21/news142_3.html
        if (my $setup_url = $csr->user_setup_url) {
            print STDERR "REDIRECT SETUP_URL TO: $setup_url\n";
            print $query->redirect(-uri => $setup_url);
            return;
        }


        #### step4 IDENTITY PROVIDERによる認証完了
        if (my $identity = $csr->verified_identity) {
            # my $user = +{ map { $_ => scalar $identity->$_ }
            #               qw( url display rss atom foaf declared_rss 
            #                 declared_atom declared_foaf foafmaker ) };
            print $query->header,"\n";
            print "<html><head></head><body>\n";
            print "<h1>OpenID logged in !!</h1>";
            print "<pre>VERIFIED_IDENTITY(OpenID, url)\n", $identity->url , "</pre>";
            print "<pre>", Dumper($identity) , "</pre>";
            print "</body></html>";
            return;
        }

        show_login_form($query);
        return;
    }

    #### step1 userがlogin formでopen_id(url)を入力
    show_login_form($query);
}


sub request_to_identity_provider {
    my ($query,$csr,$claimed_url) = @_;

    my $identity = $csr->claimed_identity($claimed_url);

    unless($identity){
        show_login_form($query, 'wrong identity'. Dumper($csr));
        return;
    }
#    print STDERR "CLAIMED_IDENTITY\n". Dumper($identity);

    my $check_url =
        $identity->check_url(return_to=>
                             URI->new($query->url.'?verify=1')->as_string,
                             trust_root => $query->url);
    print STDERR "REDIRECT TO IDENTITY PROVIDER for OpenId login\n";
    print STDERR Dumper($check_url) ,"\n";
    print $query->redirect(-uri => $check_url);
    return;
}


sub show_login_form {
    my ($query, $message) = @_;

    print $query->header, <<PAGE;
<html>
<head></head>
<body>
<form action='openid2.pl' method='POST'>
  INPUT your OpenID (url)
  <input name='openid-url' maxlength='100' style="width:500px;"
         value="https://me.yahoo.co.jp/a/S0uv.R5LVbmpBないしょ" />

  <input type='submit' value='login by OpenID' /><br/><br/>
  ex.) https://me.yahoo.co.jp/a/XXXXXXXXXXXXX<br>
  http://help.yahoo.co.jp/help/jp/edit/openid

  <pre style="margin:5px;padding:5px;border:1px solid #000">
    $message</pre>
</form>
</body></html>
PAGE

}

1;
__END__