Google, mixiなどが対応している2-legged OAuthの 練習問題でハマりつつ、PerlのOAuth::Liteがいけてることを確認した 。

Google Developers Conference参加申し込みで 出題された問題。OAuthの公開鍵を使った3-legged認証ではなく、 共有鍵を使って鍵つきダイジェスト認証をする、著者不在の 2-legged(足)な認証をする。devquizという比較的簡単な問題 なのだけれども、いままで使ったことがないので練習のつもりでやってみた。 自分でGoogle Apps premierを使っていれば、利用したかもしれないが、 そうでもないし。3-legged OAuthを見て、あーめんど、と思って 敬遠していたのもある。

自分の理解のために、手でseed作成とHMAC-SHA1ダイジェスト作成を コーディングしていたが、どうもうまくいかない。しかたなく PythonのコードやPHPのコードを探してみると、いくつかあるが 今回のGoogleのdevquizのようにPOSTで、realmをつけて、Authorization ヘッダで認証する、というコードがない。Pythonのマニュアルの 読み方を調べる直前で、PerlのOAuth::Liteがいい、というのを見て やってみると、関数に引数を与えるだけであっさり認証が完了した。

#!/usr/bin/perl 

use 5.0.8;
use strict;
use warnings;

use Data::Dumper;
use OAuth::Lite;
use OAuth::Lite::Consumer;

my $consumer = OAuth::Lite::Consumer->new(
  consumer_key		=> 'YOUR_CONSUMER_KEY',
  consumer_secret	=> 'YOUR_CONSUMER_SECRET',
  realm			=> 'devquiz',
);

my $response = $consumer->request(
    method  => 'POST',
    url     => 'http://gdd-2010-quiz-japan.appspot.com/oauth/YOUR_CONSUMER_KEY',
    params  => {
        hello => 'world'
    });

if ($response->is_success) {
    print Dumper($response->decoded_content);
} else {
    warn $response->status_line;
}

PerlのOAuth::Liteは、nonceを自動的に生成し、time()も自動的につけてくれる。 デフォルトはPOSTのAuthorization:ヘッダの、HMAC_SHA1でそろっている。

というわけで、手でコーディングしていたダイジェストの問題は以下のとおりだった。

  • seedにはPOSTの送信データであるhello=worldを含めること
  • Digest::HMA_SHA1のb64digest()メソッドは、Base64エンコードらしきことを するが、文字列の末尾のパディングをしないため、認証が通らない。
  • MIME::Base64のencode_base64()メソッドは、Base64エンコードをするが、 より大きなデータの処理を想定しているため、デフォルトで文字列の 末尾に改行コードを追加する。末尾の改行が不要なときは encode_base64($digest, "")のようにしなければならない。
  • realmはoath_なんとかのseedには入れない

mixiの説明は、Googleの説明資料の日本語訳になっていてわかりやすい。 が、PerlのOAuth::Liteを使えば、seedに関連する半分以上の説明は理解しなくてもよい。