結城浩のはてな日記 このページをアンテナに追加 RSSフィード Twitter

2006年4月24日(Mon) はてな認証API、はじめの一歩

hyuki2006-04-24

はてな認証API / ためしに作ってみました

はてな認証APIが公開されましたので、ためしてみました。

懸念事項

なおやさんところ経由ではてな認証APIの公開について(開発者さま向け)を読んで感じたこと。

  • おそらくすぐに「はてな認証APIで○○を作ってみました」的なものが登場するでしょう。おもしろいアプリが登場することを期待。
  • ただし、一般ユーザにきちんと認識させないと、悪意のある第三者が一般ユーザのパスワードを奪うアプリを作ってしまう危険性があります。たとえば「はてな認証APIを利用しています」と偽って、「ログイン名とパスワードを入力させるフォーム」を見せるアプリが出た場合、ユーザは誤解しないか。
  • それから…解説した図がほしいです。→認証部分のシーケンス図は結城が描きました(このエントリの下の方で公開しています)。

結城さんちのはてな認証APIテスト

追記:2006-04-24 21:09: とりあえず、作ってみました。以下をお試しください(ソースはすぐ下で公開)♪

これは、はてな認証サーバから返された文字列をそのまま表示するだけのアプリです。id:hyukiid:rubycoさんでうまくいくことを試しました。

追記:2006-04-24 21:49: catfrogさんへ:上の「結城さんちのはてな認証APIテスト」を試してみるとすぐにアプリのイメージは浮かぶと思います。もっとも単純なのは掲示板アプリで、はてなユーザとして認証された人だけは「名前の部分がその人のはてなダイアリーにリンクされている」というようなもの。たとえばはてなダイアリーのコメント欄がまさにそうなってますよね。

追記:2006-04-24 21:59: 一度「結城さんちのはてな認証APIテスト」用に許可すると、はてなのシステムが覚えるみたいですね。もう一度新たな気持ちでやってみたいときには、はてな認証APIのところで許可を取り消す必要があるようです。なるほど。

追記:2006-04-24 22:04: r_iizukaさんへ:URLをクリックしたときには説明用のページにジャンプさせるべきでした。実装次第というよりも、結城が入力するURLを間違えていただけです(^_^; 現在は直してあります。

追記:2006-04-24 22:07: 実装してみて気になった点。認証APIでの「説明文を用意するURL」と「認証のコールバックURL」が無関係でもよいというのはまずいのではないか。というのは、ユーザが「許可を与える」というボタンを押すときに見えているのは説明文のURLだけだから。

はてな認証APIのURLの作り方(make_api_sig.pl)

秘密鍵とapi_keyを入手してからapi_sigを作るには、以下のPerlスクリプト(make_api_sig.pl)が使えます。$secretにあなたの秘密鍵、$api_keyにあなたのapi_keyを入れ、ローカルに動かします。

use strict;
use Digest::MD5 qw(md5_hex);

my $secret = "0123456789abcdef";
my $api_key = "abcdef0123456789abcdef0123456789";
my $api_sig = md5_hex("${secret}api_key${api_key}");

print "secret = $secret\n";
print "api_key = $api_key\n";
print "api_sig = $api_sig\n";
print "URL = http://auth.hatena.ne.jp/auth?api_key=${api_key}&api_sig=${api_sig}\n";

結城さんちのはてな認証APIテストのソース(test.cgi)

追記:2006-04-24 23:27: CGIのソース(test.cgi)を公開します。$secretはあなたの秘密鍵、$api_keyはあなたのapi_key、$help_urlは説明文のURLです。

#!/usr/bin/perl
use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use Digest::MD5 qw(md5_hex);
use LWP::Simple;

my $q = new CGI;
my $cert = $q->param("cert");
my $secret = "0123456789abcdef";
my $api_key = "abcdef0123456789abcdef0123456789";
my $api_sig = md5_hex("${secret}api_key${api_key}cert${cert}");
my $help_url = "http://www.example.com/about_your_application.html";
unless ($cert) {
    print "Location: $help_url\n\n";
    exit;
}
my $content = get("http://auth.hatena.ne.jp/api/auth.json/?api_key=${api_key}&cert=${cert}&api_sig=${api_sig}");
print
    $q->header,
    $q->start_html('Hatena Auth API Test'),
    $q->start_pre,
    $content,
    $q->end_pre,
    $q->end_html;

はてな認証APIシーケンス図(概略)

追記:2006-04-25 06:15: シーケンス図を描きました(概略のみ)。

  • (1) ユーザAは、サービスXに「利用したい」という。
    • たとえばサービスXのどこかのページにアクセスすることを意味します。
  • (2) サービスXは、ユーザAに「api_keyとapi_sig1」を渡す。
    • たとえばユーザAにリンクという形で示します。
    • 便宜上、api_sigをapi_sig1とapi_sig2に分けました。両者は違う値になります。
    • api_sig1は前もって計算しておきます(たとえば上で公開しているmake_api_sig.plを使う)。
    • 秘密鍵を使うので、api_keyからapi_sig1を作るのはサービスXと「はてな」しかできません。
  • (3) ユーザAは、はてなに「id+password+api_key+api_sig1」を渡す。
    • 通常はユーザAがブラウザでアクセスすることによって渡します。
  • (4) はてなは、ユーザAに「cert」を渡す。
    • 実際には(4)と(5)は自動的にリダイレクトされますので、ユーザAは意識しません。
  • (5) ユーザAは、サービスXに「cert」を渡す。
    • ここでアクセスするのがコールバックURLです。
    • サービスXはcertは知り得るが、certからpasswordを逆算することはできません(そのようになっていなければなりません)。
  • (6) サービスXは、はてなに「api_key+cert+api_sig2」を渡す。
    • api_sig2は毎回計算します(たとえば上で公開しているtest.cgiの中で計算しています)。
    • 秘密鍵を使うので、api_keyからapi_sig2を作るのはサービスXと「はてな」しかできません。
  • (7) はてなは、サービスXに認証結果とアイコン情報などを渡す(OKなら)。
  • (8) サービスXは、認証後の画面をユーザAに提示する。

※こうやってみると、改めて一方向ハッシュ関数(メッセージダイジェスト)の重要性がよくわかりますね。

※上記のapi_sig1やapi_sig2の作成では秘密鍵を混ぜ込んでメッセージダイジェスト(MD5)を利用しているので、メッセージ認証コードの一種を作っていることになる。一方向ハッシュ関数(メッセージダイジェスト)やメッセージ認証コードについては『暗号技術入門 ―― 秘密の国のアリス』がわかりやすいですよ、と自著の宣伝:-)。

CGIまたはモジュールの実装リンク集

r_iizukar_iizuka 2006/04/24 22:17 ご丁寧に解説してくださってありがとうございます。好きなページが指定できると詐称の問題が起きるということで呼び出し元を表示するのが仕様なのかと勝手に思っていたのですが、そうでも無いようですね。説明ページと呼び出し元を併記するような形がいいんでしょうか。

hyukihyuki 2006/04/24 22:22 きっとそのあたりは、はてなーずが数日したら方策をかんがえるんじゃないでしょうかね。いまはまだ過渡期と思います。適切な説明文やサンプルコードなども提供されてほしいですよね (^_^)

snakeoilsnakeoil 2006/04/25 00:15 数日したら高木先生がはてな認証APIにもの申すに10ガバス。

kmachukmachu 2006/04/25 13:03 (2)で『api_keyからapi_sig1を作るのはサービスXと「はてな」しかできません』が、作られたapi_sig1は不変かつ公開されているので、ユーザが再利用することはできちゃいますね。
(2)(3)のセキュリティに秘密鍵やapi_sig1はあまり関係が無く、事前のコールバックURLの登録でセキュリティが担保されていると思っています。

hyukihyuki 2006/04/25 14:18 なるほど。ちょうどメールでFromは詐称できてもToで受ける方は本人に届くというのと似ていますね(ってよけいわかりにくいたとえかな)。

はじめの一歩はじめの一歩 2010/04/23 15:20
携帯で無料&簡単に画像が読み放題です!
会員登録もありません!
FAIRYTAIL?エアギア?あねどきっの人気マンガ作品も充実!!
一度遊びに来て下さい!!
詳細はこちらになります▽

はじめの一歩 画像
http://comic.fansfree.com/magazine/ippo/

名探偵コナン 画像
http://comic.fansfree.com/sunday/conan/

アライブ 最終進化的少年
http://comic.fansfree.com/magazine/alive/

クロスゲーム 画像
http://comic.fansfree.com/sunday/crossgame/