PerlでOpenIDの認証サイトを作ってみた

今までOpenIDについては、本やWebからの知識だけだったので、実際にRPを実装してみました。
といっても、Net::OpenID::Consumerを使って、認証デモを作っただけです。

OpenIDの認証の流れ

  1. OpenIDアカウント(Claimed Identifier)入力
  2. RP(Relying Party)でのOP(OpenID Provider)エンドポイントの抽出、OPへのリダイレクト
  3. OPにてユーザ認証
  4. 認証結果の送信(OP->UserAgent->RP)
  5. RPでの認証結果解析

RPの実装

RPの実装の際、以下の機能が必要となります。

  1. OpenIDアカウント(Claimed Identifier)の入力フォーム
  2. OpenIDアカウントからOPのエンドポイントURLを抽出、UserAgentをリダイレクトさせる
  3. 認証結果を伴ないOPからリダイレクトしてきたUserAgentの受け入れ、認証結果を解析する

今回のデモでは、上記機能を

に実装しました。

プログラム

事前に、Net::OpenID::ConsumerとCrypt::SSLeayのインストールが必要です。

cpan> install Net::OpenID::Consumer
cpan> install Crypt::SSLeay
  • index.html
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>OpenID Authentication Demo</title>
    <style>
      input.openid-url {
      background: url(./openid_logo.gif) no-repeat;
      background-position: 0 50%;
      padding-left: 20px;
      width: 320px;
      }
    </style>
  </head>
  <body>
    <h1>OpenID Authentication Demo</h1>
    <p>
      OpenIDを入力して、Loginボタンを押してください。<br>
      <form action="./openid_redirect.cgi" method="POST">
      <input class="openid-url" name="openid-url"><input type="submit" value="Login">
      </form>
    </p>
  </body>
</html>
#! perl

use strict;
use warnings;
use CGI;
use LWP::UserAgent;
use Net::OpenID::Consumer;

my $q = CGI->new;
$q->charset('utf-8');

my $csr = Net::OpenID::Consumer->new(
   ua => LWP::UserAgent->new,
   args => $q,
   consumer_secret => 'hogehoge',
   required_root => 'http://xxxxx/',
);

my $openid_url = $q->param('openid-url');
my $claimed_identity = $csr->claimed_identity($openid_url);
my $check_url = $claimed_identity->check_url(
    return_to => 'http://xxxxx/openid_login.cgi',
    trust_root => 'http://xxxxx/',
);
print $q->redirect(-uri => $check_url);

__END__
#! perl

use strict;
use warnings;
use CGI;
use LWP::UserAgent;
use Net::OpenID::Consumer;
use Data::Dumper;

my $q = CGI->new;
$q->charset('utf-8');

my $csr = Net::OpenID::Consumer->new(
   ua => LWP::UserAgent->new,
   args => $q,
   consumer_secret => 'hogehoge',
   required_root => 'http://xxxxx/',
);

if (my $user_setup_url = $csr->user_setup_url) {
    print $q->redirect($user_setup_url);
} elsif (my $verified_identity = $csr->verified_identity) {
    my $user = +{map {$_ => scalar $verified_identity->$_} qw(url display rss atom foaf declared_rss declared_atom declared_foaf foafmaker)};
    print $q->header;
    print "Logined OK!!<br>";
    print "<pre>" . Dumper($user) . "</pre>"
} elsif ($csr->user_cancel) {
    print $q->header;
    print "Canceled!!<br>";
} else {
    print $q->header;
    print "Error!!<br>";
}

__END__

index.htmlで使用しているopenid_logo.gifは、ここから取得してください。