at posts/single.html

はてなの認証API (2)

はてなの認証APIがコールバックURLへのパラメータ指定をサポートしたみたい。 これまではコールバックURL(はてなでの認証後に戻ってくるURL)は固定だったけど、これにパラメータを付けられるというもの。 Kazuho@Cybozu Labsに、具体的なメリットが書かれている(以下引用)。

パラメータを指定できたほうが良いと思います。固定のままでも、サードパーティアプリ側で Cookie を使えば、パラメータ指定と同等のことはできますが、処理が煩雑になるので。

分かるような分からないような。僕の勉強不足だな…。 前提として、「はてなで認証する前の情報を、認証後も保持しておきたい」ってのがあるのか。 以下の処理を例に考えてみる。

  1. ユーザが、検索サービスに対して何かアクションを起こす(例えば、検索クエリを投げるなど)
  2. サービスは、はてなAPIを使ってユーザを認証する(一度、はてなの認証サーバにリダイレクトする)
  3. サービスは、ユーザに対して応答を返す

コールバックURLが固定だと、ユーザが[2]ではてなから戻ってきた時点で[1]でのアクションの情報(例では検索クエリの内容)が失われてしまう。 [1]の時点で Cookie を発行し、[3]で Cookie からアクションの情報を取得することもできる。 でもそれより、[1]から[2]へのリダイレクト時にパラメータとして渡してあげた方が処理が楽ということかな。 確かに、使い捨ての情報だったらクエリに入れられた方が楽かな。

POST リクエストに対して認証が必要になってリダイレクトするようなケースでは、 CSRF を防ぐために、 Cookie とコールバック URL のパラメタを組み合わせる必要がありますので、そのような動作をサポートしたい (たとえば、ブログのコメントをポストする際に認証を要求するようなウェブアプリに対応したい) のであれば、パラメータ指定は必須になります。

CSRF を防ぐためには、コメントフォームに何かしらのキー(セッションキーだったりワンタイムキーだったり)を埋め込む必要がある。 んで、そのキーの情報は Cookie に入れることはできない(Cookieに入れると CSRF 対策にならない)。 だから、コールバックURLへのパラメータにそのキーを入れたいってことかな。

「アクション」→「認証」→「アクションの応答」というシーケンスだから、処理が複雑なのかも。 事前に認証されていないとアクションができない(例えばブログのコメントフォーム自体が表示されない)という作りにすれば、コールバックURLへのパラメータは不要な気がする。

パラメータ指定への留意点

Kazuho@Cybozu Labs のその後のエントリーで、パラメータ指定に対応する場合の注意点が挙げられている。 勉強になるなぁ。

サードパーティアプリケーション側で、未ログインだった場合にクエリパラメータをそのまま認証サーバへリダイレクトするようなコードを書いてしまうと、それを署名の偽造に利用される可能性が出てきてしまう

現時点では、サードパーティアプリケーション側で汎用的なログイン処理を書く場合には、cert パラメータをログイン URL に含めないよう注意する必要がある

なるほど。 これは認証API側の問題ではなく、アプリ側の問題かな。 「ユーザからの入力をそのまま出力に使ってはいけない」という Web アプリの原則に従って、認証サーバへ渡すパラメータは事前にアプリ側でチェックすべき、と。

この問題については、今後の仕様改訂の際に、 URL Path も含めてハッシュ値を算出するようにすれば良い

この解決策はよく分からなかった。 何が正しいパラメータで何が不正なパラメータかはアプリにしか分からないので、ハッシュに URL を含めても変わらないのでは。 何か勘違いしているかな…。

MD5 と HMAC

同じく、 Kazuho@Cybozu Labs のエントリで、署名の生成に MD5 は危険だから HMAC を使った方がいいと指摘されている。

こういう場合は、HMAC を使うべきだと思います。現在のやり方だと、秘密鍵は被署名データの先頭にしか作用しないので、末尾を上手に構築することで攻撃が (理論的には) 成立します。

『[秘密鍵]api_key[API_KEY]appendDATA』 のようなデータの MD5 値が既知の場合に、『[秘密鍵]api_key[API_KEY]appendDATA\x80\0\0\0......\0\0\x02\x08cert[任意の cert 値]』の MD5 値は、秘密鍵を知らなくても算出することができます

「ある値」のハッシュ値が分かれば、「ある値+α」のハッシュ値が分かるということか。 これが本当なら、僕のハッシュ関数への理解が根本的に間違っていることになるなぁ…。 (もしくは、ハッシュ関数全般の危険性じゃなくて、MD5固有の話?)

  • ハッシュ値から元の値を推測することが困難
  • 同じハッシュ値を持つ2つのメッセージを見つけることが困難

というのがハッシュ値の条件の一部。 確かに「ある条件を満たせば、メッセージを知らなくてもそのハッシュ値を推測できる」というのは、これら条件と矛盾しないか。

それで、 MD5 ではなく HMAC を使えばいいということなんだけど、 HMAC の仕組みと認証APIの署名の仕組みは似ている。 (以下、HMAC の仕組みについては、結城さんの暗号技術入門を参考にしました)

HMAC
hash(opadkey + hash(ipadkey + message))
はてな認証API
hash(secret_key + message)

HMAC の opadkey と ipadkey は、秘密鍵 (secret key) を2つに分けたようなもの。 秘密鍵を2つに分けて2回ハッシュを取ると問題なくて、1回だと問題があるということ?(←よく分かってない)

ここは少し勉強して、出直さないとな…。

関連する日記