風柳メモ

ソフトウェア・プログラミング関連の覚書が中心

クロスコメント:IFRAME+window.name通信によるクロスサイト認証付きWeb拍手の試作

クロスサイトで投稿するときにユーザの手動クリックが要求されるような仕組みを考える

『あるサイト[A]上のページ(a)からIFRAMEで別の(ドメインの)サイト[B]上のページ(b)を読み出した場合、ページ(b)上のボタンは、ページ(a)上(のスクリプト)からは自動でクリックは出来ない』と思っているのですが(そもそもこの前提が違うかも)。


これを踏まえて、サイト[B]が提供するサービスを、別サイト[A]から利用したい場合、

  1. サイト[B]が提供する認証ボタンを含んだページ(b)を、サイト[B]上のページ(a)からIFRAMEにより表示(ページ(a)ではIFRAME下のwindow.nameを監視開始)。
  2. ユーザが、ページ(b)上の認証ボタンをクリック。
  3. 認証ボタンがクリックされたら、ページ(b)はサイト[B]上サービスから一時キーKを取得、window.nameに設定後、サイト[A]上のページへ遷移(こうしないと、ブラウザのセキュリティ制限上、サイト[A]上のページ(a)からIFRAME下のwindow.nameを参照出来ない)。
  4. IFRAME下のwindow.nameを監視しているページ(a)は、これが参照可能&変化ありの場合、そこに設定された一時キーKを取得。
  5. 以降、ページ(a)では、サイト[B]に対してリクエストを出すときには、一時キーKを使用。
  6. サイト[B]では、リクエストに含まれる一時キーKを確認することで、正常に認証されたユーザだと見なす。



このような仕組みなら、2. の手順でユーザによる手動操作が必要となるため、ユーザが意図しない形での不正利用(CSRF)が押さえられ、かつ、サイト[A]ではページ遷移することのなくサイト[B]のサービスが利用できそうな気がしました。

で、やっつけで実装してみたのが

これ。

クロスコメント:IFRAME+window.name通信によるクロスサイト認証付きWeb拍手・サンプル

※上記説明で、サイト[A]とサイト[B]はそれぞれ、『さくら上のサーバ(furyu-tei.sakura.ne.jp)』と『 Google App Engine 上のサーバ(furyu-tei.appspot.com)』になります。

そもそものきっかけは

はてな☆ログ:はてなスターを利用した足跡ログ取得サンプル - 風柳メモ

で触れた、

はてなスターの認証強化について - はてなスター日記

の中の、「JavaScriptが実行可能な環境で意図的にスクリプトを仕込むことで意図しない☆が付く」をなんとか回避する方法はないか、ということ。
現状は、認証用のキー(rsk)取得そのものにJSONP使っているため、結局はスクリプトで自動的に☆を付けられてしまうのですよね。
上記手法なら、最初のスターをつけるときのみ、"Add Star"にマウスオーバしたらかぶせる形で認証ボタン(IFRAME)を表示させてやれば……とか思ったので。

気になっているのが

  1. そもそも、前提が正しいのか?(クロスサイトでも自動的にボタンをクリック出来てしまうようなら、直ちに瓦解する)
  2. ユーザを特定するキーは二つ(データベース用KEYと乱数のペア)あるのだけれど、これを二つともwindow.nameで渡しているので、あまり宜しくない。本当ならどちらか一方はCookieにしてサイト[B](furyu-tei.appspot.com)の範囲でのみ有効にすべきで、実際最初はそうやっていたのだけれど、FirefoxとSafariはOKなのに、IE7とOperaではNG。IE7でセキュリティレベルを落すと動くので、どうも、後の二つは(標準設定では)IFRAME内でのCookie設定は無効になってしまうような制限がかけられているのではないかと推測。
  3. 排他制御とか。(現状では同一ブラウザの複数のタブ/窓でクロスコメントを同時に開くと動作がおかしくなる)
  4. サイト[B]上のページ(b)がサイト[A]上ページへ遷移するときの、遷移先のURLをどうやって決めるか。