はてなのOAuthを使ってみる

パスワードによるWSSE認証が終了するらしい・・・というか、今日の時点ですでに終了してるのかな?
はてな各種APIでのパスワードによるWSSE認証を2014年3月5日に終了します(開発者向け) - Hatena Developer Blog
APIキーかOAuth、ということになるんだろうけど、試しにOAuthを使ってみることにした。

Consumer key を取得して OAuth 開発をはじめよう - Hatena Developer Center

・・・・・・。

正直よく分からん。「典型的なリクエスト・レスポンスは次のようになります。」って言われても。どんなパラメーターを送ると何が返ってくるか、の説明がないとコレだけ読んでも全然分からんのだけど・・・。

ちょろっとアプリ作りたいってだけの人に詳細はRFC読め、って不親切すぎじゃねーかって思うんだが・・・。

サンプルコードもサーバーサイドアプリのサンプルで読みにくいし・・・。

GoogleのOAuthを試したときは解説が分かりやすくて助かったのだけど、まあ、安定のはてなクオリティってことか。

あと、これはOAuthが2.0じゃなくて1.0aであることが原因のようですが、twitterとかgoogleに比べてメチャメチャめんどくさいな。いちいちoauth_signatureを作って送らなきゃいけないとか、認証用のURLを作るためにリクエストークンとか言うのを取ってこなきゃいけないとか。

練習のためにLWPで頑張ろうと思ったけど、さすがに面倒くさすぎてライブラリーに頼ることにした。OAuth2.0に移行すればいいのになー。

OAuth 1.0での開発を経験された方なら、おそらく誰しも署名と複雑な認証フローには苦しめられたのではないでしょうか?

この仕組みが複雑なため、OAuthクライアントを作成するためにはOAuthのライブラリが必須でした。しかし複雑なため、ライブラリにバグが存在することもしばしばありました。ライブラリが存在しない言語でOAuthを使用したい開発者は諦めざるを得ないような状況でした。

OAuth 2.0でWebサービスの利用方法はどう変わるか(1/3)- @IT

ですよねー


OAuth1.0の仕様に関してはYahooのページが参考になりました。さすがやふー。

http://developer.yahoo.co.jp/other/oauth/endpoint.html

サンプル

愚痴はともかく。

まずはトークンをゲットするところから。

use strict;
use warnings;
use utf8;

use OAuth::Lite::Consumer;
use OAuth::Lite::Token;

my $consumer = OAuth::Lite::Consumer->new(
  consumer_key       => '[Your consumer key]',
  consumer_secret    => '[Your consumer secret]',
  site               => q{https://www.hatena.com},
  request_token_path => q{/oauth/initiate},
  access_token_path  => q{/oauth/token},
  authorize_path     => q{https://www.hatena.ne.jp/oauth/authorize},
);

my $request_token = $consumer->get_request_token(
  callback_url => 'oob',
  scope        => 'read_public,write_public,read_private,write_private',
);

printf("Authorize this app and enter the PIN# from:\n%s\n\nPIN = ", $consumer->url_to_authorize(token=>$request_token));
my $pin = <STDIN>; # wait for input
$pin =~ tr/\x0A\x0D//d;

my $access_token = $consumer->get_access_token(
  token    => $request_token,
  verifier => $pin,
);

printf("oauth_token  : %s\n", $access_token->token);
printf("oauth_secret : %s\n", $access_token->secret);
Authorize this app and enter the PIN# from:
https://www.hatena.ne.jp/oauth/authorize?oauth_token=[Request token]

PIN = [verification code]

oauth_token  : [Your OAuth token]
oauth_secret : [Your OAuth secret]

実際にどんなデータがやり取りされるのか?については、はてな様の説明の「典型的なリクエスト・レスポンス」とやらを見るとよいのではないかと。

で、ゲットしたトークンの使い方は

use strict;
use warnings;
use utf8;

use OAuth::Lite::Consumer;
use OAuth::Lite::Token;

my $consumer = OAuth::Lite::Consumer->new(
  consumer_key       => '[Your consumer key]',
  consumer_secret    => '[Your consumer secret]',
);

my $access_token    = OAuth::Lite::Token->new(
  token  => '[Your OAuth token]',
  secret => '[Your OAuth secret]',
);

my $res = $consumer->request(
  method => 'GET',
  url    => q{http://n.hatena.com/applications/my.json},
  token  => $access_token,
);

print $res->decoded_content;
$ perl sample.pl
{"profile_image_url":"http://cdn1.www.st-hatena.com/users/kk/kkobayashi/profile.gif?1383898898","url_name":"kkobayashi","display_name":"kkobayashi"}

こんな感じか。さすがにライブラリー使うと簡単にできるな。

ちなみにアクセストークンを取らずにURLにアクセスすると

$ curl -o - http://n.hatena.com/applications/my.json
{"display_name":"ゲスト"}

OAuth::Lite::Consume::requestが返すのは HTTP::Response オブジェクトらしい。

あと、自動的に"Accept-Encoding: gzip"ヘッダーを付けてリクエストするので、中身を取り出すときはdecoded_contentを使うとよい。


・・・うーん、とはいえ、いちいち OAuth::Lite::Consumer を通してリクエストするのがかったるいな。APIキーでいいような気がしてきた。OAuthに比べて何か制限ってあるんだっけ?