at posts/single.html

Flickr API の認証

tDiary の Flickr プラグインを改造して、Google Mapsの位置情報を簡単にタグに埋め込める (geotagged) ようにしたいと思っている。 そのためには、プラグインから Flickr 上の写真にタグを埋め込まないといけない。 タグを埋め込むには認証が必要…ということで、 Flickr API の認証の仕組みを調べてみた。

情報源は Flickr の公式ドキュメントから。

事前準備 (Flickr API Key)

Flickr の API を使うには、 API Key が必要。 API Key は、サービス (Flickr API を使うアプリケーション) を一意に識別するために使われるみたい。 この API Key は Flickr Services で取得できる。

いちばん簡単な方法

Flickr API では、ユーザの ID とパスワードを使って Flickr API にアクセスすることができる。 たとえば、ユーザのお気に入り (Favorites) 写真の一覧を得る flickr.favorites.getList を使うには、以下の URL にアクセスすればいい。 ID (email) とパスワードは URL の一部として埋め込む。

http://flickr.com/services/rest/?method=flickr.favorites.getList&api_key=API_KEY&email=user@example.com&password=PASSWORD

「API_KEY」には上記で取得した API Key が、「PASSWORD」にはそのユーザのパスワードが入る。 他の API も同じような方法で使うことができる。

この方法はシンプルで分かりやすいけど、実はあまり良い方法じゃない。 API を使うサービスが、ユーザの ID とパスワードを知ることになるから、サービス側が悪意を持てばアカウントを乗っ取ったり、ユーザの写真を全部消したりできちゃう。 それに、ID とパスワードが URL に 入っているから、 Web サーバのアクセスログにも残っちゃう。

そこで、 Flickr には認証のための仕組みが用意されている。

トークンを使った認証

まずはおさらい。 Flickr の認証を考える時の登場人物は3人いる。

  1. 利用者 (ユーザ)
  2. Flickr
  3. Flickr API を使ったサービス (以下サービス)

ここで、「ユーザ」が「サービス」に ID とパスワードを教えちゃうのが問題なんだった。 そこで Flickr API では、代わりに「トークン」を使った認証ができるようになっている。 「トークン」は一種の委任状のようなもので、ユーザ本人に代わって Flickr 上のデータへのアクセスを許可していると思えばいい。

flickr (1)

「ユーザ」は「サービス」にトークン (委任状) を発行し、そのトークンを使って「サービス」が Flickr にアクセスするというモデルになる。 こうすれば、「サービス」にパスワードを教えなくてすむ。

ちなみに、トークンは「182657-31ba003033cd22f9」のようなただの文字列。 そのトークンがどういう意味を持つかは、Flickr側で管理しているみたい。

トークン発行の流れ

もう少し詳しく、トークン発行の流れを見てみる。 詳細は、前述の Flickr Authentication API Web Applications How-To が参考になる。

flickr (2)

(1) 「サービス」が Flickr の認証画面へのリンクを生成する。 このリンクには、「サービス」の api_key と、必要となるアクセス権限 perm (read, write, delete, none のいずれか) が含まれている。

http://flickr.com/services/auth/?api_key=API_KEY&perm=write&api_sig=SIGNATURE

この例では、 API_KEY というサービスが書き込み権限 (write) を要求している。 api_sig は偽造防止のための文字列。詳しくは後述。

(2) ユーザがこのリンクをクリックすると、 Flickr のログイン画面が表示される。 すでにユーザが Flickr にログイン済みの場合はログイン画面ではなく、このサービスにトークンを発行してもいいかどうかの確認画面が表示される。

(3) ユーザがログインすると、「サービス」の URL にリダイレクトされる。 このとき、 URL の一部に frob という文字列が含まれている。 frob はトークンの引換券みたいなものらしい。

実は、 URL での戻り先は、あらかじめ固定的に決めておく必要がある。 Flickr Services のページで、Authentication の「Edit configuration」のリンクを開き、Authentication Type: を Web Application に、 を戻り先の URL にしておく。 つまり、1つの API Key に対して戻り先は1つだけになる。

もし、 Callback URL が http://exapmle.com/ だとすると戻り先の URL は

http://exapmle.com/?frob=353171-81f28a87419e50e9

などになる。

(4)(5) 取得した frob をキーにして、トークンを取得する。 frob が先ほどの例だとすると、サービスが直接

http://flickr.com/services/rest/?method=flickr.auth.getToken&frob=353171-81f28a87419e50e9&api_sig=SIGNATURE

にアクセスする。 ここでも、 api_sig は偽造防止のための文字列。 この結果は、XML形式でトークンが返ってくる。 これには、トークンの ID, 権限 (perm), ユーザIDが含まれている。

なんで、(3) で直接トークンを渡さないのかはよく分かっていない。 ユーザにトークンを見せないようにするため、かな? ドキュメントのどこかに書いてあるのかも。

ここまで見てきたように、ユーザはサービスごとにトークンを発行することになる (あるトークンを別のサイトにコピーしても使えないようになっている)。 自分がどこにトークンを発行したかは、アカウントページの Authentication listで確認できる。 発行したトークンの取り消しも可能。

トークンの偽造防止 (api_sig)

先ほどの例では、メソッドの呼び出し時に api_sig というパラメータを渡している。 これは、偽のサービスが勝手に Flickr の API を呼び出せないようにするために使われる。

flickr (3)

API 呼び出し時には、サービスを識別する「api_key」と、ユーザを識別する「トークン」が Flickr に送られる。 このうち api_key は第三者が簡単に取得できる。 もしユーザのトークンが盗まれると、他の偽サービスがそのトークンに対応するユーザのデータを好き勝手に操作できるようになってしまう。 ユーザのトークンはサービスから Flickr に送られるデータ (HTTP の QUERY_STRING) に含まれるので、盗まれる危険性はそれなりにあると考えた方がよさそう。

第三者にトークンが盗まれても被害を少なくするための仕組みが、「api_sig」という署名になる。 署名の仕組みは比較的シンプル。 まず、サービスと Flickr の間で共通の文字列 (SECRET) を保持しておく *1 。 この SECRET とリクエストデータを連結した文字列をハッシュ化 (MD5) したものが、署名データになる。 第三者がトークンを盗んだとしても、 SECRET が分からないと署名は作れないという仕組み。 最初の取得時を除くと、 SECRET が Flickr とサービスの間でやり取りされることはないため、SECRET 自体が盗まれる危険性はトークンよりも低い。

ただし api_sig とトークンさえ分かれば、 SECRET が分からなかったとしても偽サービスが同じリクエストを送ることができる(リプレイアタック)。 SECRET があるからといって、トークンの管理はしっかりとしなくちゃいけないだろうね。

追記 (2006/5/7)

現状の方式では、ある条件を満たせば SECRET を知らなくても署名値を推測することができるそうです。 独自の方式ではなく、 HMAC を使うべきでしょう。

関連する日記