09 June 2013

ソーシャルプラットフォームでの signed request のフロー

いわゆるソーシャルゲームなど、あるプラットフォームの iframe 内で動くサードパーティ web アプリ、OAuth を使ってプラットフォームの API をたたいてエンドユーザーにサービスを提供するようなもの。この手のアプリでは、まずプラットフォームにアプリケーション登録し、アプリの ID や OAuth の consumerkey, consumersecret などの必要な情報を払いだしてもらう。ユーザーがプラットフォーム内から特定のアプリにアクセスしようとすると、プラットフォーム側は iframe にサードパーティのアプリを読み込んでユーザーに提供する。iframe からリクエストをおくるサードパーティ側のエンドポイントは事前のアプリケーション登録時に設定しておく。

サードパーティアプリ側では当然、プラットフォームのユーザーごとに情報を保存して別の挙動をさせたり、あるいはバッチ系の操作が必要なら OAuth のアクセストークンもデータストアに持っている可能性もある。プラットフォーム側からリクエストしているのはどのユーザーか、これはユーザーのログインセッションを持つプラットフォーム側だけが知り得る情報だ。誰がリクエストしているかをプラットフォーム側がアプリケーション側に伝えないとまともなアプリは作れない。

ではプラットフォーム側の iframe からは単にユーザー ID をクエリストリングにつけてサードパーティアプリを呼び出すことにしよう。当然ながらこの方式には脆弱性がある。悪意のある第三者が適当にクエリストリングを偽装してアプリ側にリクエストを送ると、簡単にそのユーザーになりすましてアプリを利用することができてしまう。

対策もストレートに、プラットフォーム側とアプリ側の 2 者しか知り得ない情報でリクエストをチェックすればよい。この場合最も簡単なのはプラットフォームが払いだしている OAuth の consumer_secret だ。一般的なのは、プラットフォーム側はアプリケーション側にユーザー ID などの必要な情報とともに、それを SHA1 でハッシュ化したシグネチャを送る。ハッシュ化の際には対象のアプリに払いだした consumer_secret をキーに用いる。リクエストをうけたアプリ側では、送られた内容からシグネチャとそうでない部分 (データ) を分離。データを自分の consumer_secret でハッシュ化し、シグネチャと一致するか調べる。こうしてリクエスト元の正当性を調査するという仕組みだ。

このへんの話は、仕様としては opensocial で定められている。

各ソーシャルプラットフォームのベンダーのドキュメントを読むと具体的でわかりやすい。Facebook は、全般的にそうだが今回も例に漏れず、オープンな仕様に若干独自のアレンジを加えた仕様になっている。