mixiアプリ » 技術仕様(旧方式) » モバイル » OAuth Signatureの検証方法について
OAuth Signatureの検証方法について
mixiアプリの開発において、mixi側のサーバからアプリケーション開発者のサーバにHTTPリクエストが送信されることがあります。アプリケーション開発者のサーバのURLに対して、ユーザや悪意を持った第三者が直接リクエストを送ると意図しない結果を引き起こしてしまうことがあります。このような問題を防ぐために、リクエストがmixiサーバからのものであるかどうかを必ず検証してください。
mixiサーバからのリクエストには、AuthorizationヘッダにOAuth Signatureという署名が必ず付加されていますので、これを検証することで改ざん検知が可能です。
以下で実際に検証する方法を説明します。
送信されるAuthorizationヘッダ
mixiサーバから送信されるHTTPリクエストには、次のようなHTTPヘッダが付加されています。
Authorization = OAuth realm="", oauth_consumer_key="bc906fac81f581c3c96a", oauth_nonce="9dc8fbca0e51842e7449", oauth_signature="Ky%2F6LlDHpHX1EZMRi5mfUl9vxqY%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1254282755", oauth_version="1.0"
検証する値は、この中の”oauth_signature”になります。”oauth_signature”以外の値は、開発者サーバ側でOAuth Signatureを生成する際に利用します。送信されてきた”oauth_signature”と開発者側で生成した値が一致するかどうかを確認することで検証を行います。各パラメータの説明は以下の通りです。
| oauth_consumer_key | 事前に発行されたconsumer_key |
| oauth_nonce | ランダムな文字列。 |
| oauth_signature | APIリクエストの妥当性を検証するための署名です。Signatureの生成方法については次項を参照してください。 |
| oauth_signature_method | 署名方式。’HMAC-SHA1′固定 |
| oauth_timestamp | UNIXタイムスタンプ |
| oauth_version | 1.0 |
OAuth Signatureの生成方法
http://example.com/foo/?opensocial_app_id=123&opensocial_owner_id=xxxxxxxx
にGETリクエストが送信された場合を例として、OAuth Signatureの生成方法を以下に説明します。
まず、署名生成に必要なベース文字列を生成するために次の値を用意します。
- HTTPリクエストメソッド
- リクエストURL。クエリーパラメータは含めないようにします。
- OAuthの処理に必要な各種パラメータを設定します。クエリーパラメータはこちらに含めます。パラメータの順序は、予めパラメータ名のアルファベット順にソートしておく必要があります。
例えば、下記のような値を用意します。
- GET
- http://example.com/foo/
- oauth_consumer_key=bc906fac81f581c3c96a&oauth_nonce=9dc8fbca0e51842e7449&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1254282755&oauth_version=1.0&opensocial_app_id=123&opensocial_owner_id=xxxxxxxx
これらをURIエスケープした後に & で連結して、ベース文字列を生成します。
GET&http%3A%2F%2Fexample.com%2Ffoo%2F&oauth_consumer_key%3Dbc906fac81f581c3c96a %26oauth_nonce%3D9dc8fbca0e51842e7449%26oauth_signature_method%3DHMAC-SHA1%26 oauth_timestamp%3D1254282755%26oauth_version%3D1.0%26opensocial_app_id%3D123%26 opensocial_owner_id%3Dxxxxxxxx
次に、このベース文字列をHMAC-SHA1によってダイジェスト値を生成し、BASE64でエンコードすることによってSignatureを生成します。この際、利用する共有キーはconsumer_secretと空のToken Secretを&で連結したものになります。consumer_secretはアプリケーション登録時に発行されたものを利用します。例えば、consumer_secretが79e0a55cde43e7dc86fd1e1366d6bd6ac7771db8なら79e0a55cde43e7dc86fd1e1366d6bd6ac7771db8&になります。こうして、シグニチャは以下のようになります。
Ky/6LlDHpHX1EZMRi5mfUl9vxqY=
こうして生成されたパラメータをAuthorizationヘッダのoauth_signatureと比較することで検証が可能です。もし、このSignatureが一致しない場合には、適切なエラー画面を表示するなどの処理を行ってください。
より詳細な仕様については、OAuth Consumer Request 1.0 Draft 1を参照ください。
Postリクエスト時のSignature生成
Postリクエストが送信された場合には注意が必要です、OAuth Core 1.0にもある通りPostリクエストの場合でもリクエストボディをベース文字列に含むのがOAuthの仕様として定義されておりますが、mixiでは歴史的な事情によりリクエストボディを含まずにSignatureを生成する方法を採用しています。
POST /foo/?opensocial_owner_id=xxxxxxxxxxxxx HTTP/1.0 host: example.com Content-Length: 13 foo=1&bar=abc
上記のようなPOSTリクエストが送信された場合、ベース文字列は以下のようになります。
POST&http%3A%2F%2Fexample.com%2Ffoo%2F&oauth_consumer_key%3Dbc906fac81f581c3c96a %26oauth_nonce%3D9dc8fbca0e51842e7449%26oauth_signature_method%3DHMAC-SHA1%26 oauth_timestamp%3D1254282755%26oauth_version%3D1.0%26opensocial_owner_id%3Dxxxxxxxx
ご覧の通り、リクエストボディを含まずにベース文字列を生成します。 ただし、含まないのはあくまでリクエストボディです。URL内に付与されたクエリパラメータはGET同様ベース文字列に含む必要がありますのでご注意ください。
参考文献
OAuth Consumer Request 1.0 Draft 1
http://oauth.googlecode.com/svn/spec/ext/consumer_request/1.0/drafts/1/spec.html
December 2007.