ぼくがかんがえたおーぷんそーしゃる その3
- JavaScript を(極力)使わずに OpenSocial アプリケーションを作る講座、第三回です
- 外部サーバ上で security token がどのアプリに対して発行されたものか検証する方法とは
- Signed Requests を使います
- コンテナから外部サーバのエンドポイントに対して、Signed Requests を投げさせ、レスポンスに含まれる opensocial_app_url をチェックすることで、どのアプリの st であるか確認します
- Signed Requests を使います
- まず、コンテナから Signed Requests を投げさせる
- gadgets.io.makeRequest() を実行しているガジェットをモニタすると内部でこんなことになっています
POST /gadgets/makeRequest HTTP/1.1
Host: 7f17fe5993881228b01b387a41e93a45edb7b149.app0.mixi-platform.com
X-Mixi-Platform-IO: 1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
url=http%3A%2F%2Fmxfarm.rekoo.com%2Fembed_swf%2F&httpMethod=POST&headers=Content-Type%3Dapplication%252Fx-www-form-urlencoded&postData=***&authz=signed&st=***&contentType=JSON&numEntries=3&getSummaries=false&signOwner=true&signViewer=true&gadget=http%3A%2F%2Fmxfarm.rekoo.com%2F%3Fv%3D1258954460&container=default&bypassSpecCache=
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
throw 1; < don't be evil' >{"http://mxfarm.rekoo.com/embed_swf/":{"body":"{\n \"session_name\": \"sessionid\", \n \"return_code\": 0, \n \"uid\": \"11325239\", \n \"server_now\": 1258974369.6, \n \"session_value\": \"***\"\n}","rc":200}}
- 試してみると、http://app0.mixi-platform.com/gadgets/makeRequest に少なくとも下記のパラメータを POST で渡せばよいことがわかります
- X-Mixi-Platform-IO: 1
- httpMethod
- 外部サーバをたたくときの method
- url
- 外部サーバのエンドポイント
- authz=signed
- request に署名する
- st
- security token
- 次に、外部サーバ上に Signed Requests を検証するためのエンドポイントを用意する
- こいつはサンプルコードまんまでいいです
- perl の場合
- [僕] OAuth の署名付きリクエストを受け取る を修正させていただきました
- これを http://twixi.dyndns.org/fetchme.cgi とします
use CGI; use OAuth::Lite::SignatureMethod::RSA_SHA1; use OAuth::Lite::Util qw(create_signature_base_string); use JSON; my $public_key = <<__END_OF_PUBLIC__; -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDASPndWVBy/VYe99aVM/5PWVdS D3Vb5uAlK4cAPz091V/1SOeL3YSRuOposPMDjf5TlQuUr/TmNE6cbAUFV0hLFQuB 69KmJN+Bt8JwptFbuFetNKaMVESntg69+VPeuvuqo2+Ob7dcTXnvNxTfdJcwga9f W5Af9jh82kQTWmZf5QIDAQAB -----END PUBLIC KEY----- __END_OF_PUBLIC__ my $verifier = OAuth::Lite::SignatureMethod::RSA_SHA1->new( consumer_secret => $public_key, ); my $cgi = CGI->new; my $params = $cgi->Vars; my $oauth_signature = $params->{oauth_signature}; delete $params->{oauth_signature}; my $base_string = create_signature_base_string( $cgi->request_method, $cgi->url, $params, ); my $result = $verifier->verify($base_string, $oauth_signature); print $cgi->header, to_json({ validated => $result ? 1 : 0, query => $params, });
- いよいよ、外部サーバに渡された st の opensocial_app_url を検証してみる
- 外部サーバから http://app0.mixi-platform.com/gadgets/makeRequest を POST でたたき、http://twixi.dyndns.org/fetchme.cgi に Signed Requests を投げさせて結果を受け取ります
use CGI; use LWP::UserAgent; use JSON; my $q = CGI->new; my $ua = LWP::UserAgent->new; my $res = $ua->post( 'http://app0.mixi-platform.com/gadgets/makeRequest', { httpMethod => 'GET', url => 'http://twixi.dyndns.org/fetchme.cgi', authz => 'signed', st => $q->param('st'), }, 'X-Mixi-Platform-IO' => '1', ); my $content = from_json($1) if $res->content =~ /({.+)$/; my $body = from_json($content->{$url}->{body}); print $q->header(-type => 'text/plain', -charset => 'utf-8'); print 'validated: ' . $body->{validated} . "\n"; print 'opensocial_app_url: ' . $body->{query}->{opensocial_app_url} . "\n"; print 'opensocial_viewer_id: ' . $body->{query}->{opensocial_viewer_id} . "\n";
-
- これで opensocial_app_url が取れました
- gadget.xml を置いた URL と等しいか確認しましょう
- opensocial_viewer_id なども同時に取れるので、プロフィール情報が必要なければ、RESTful API を叩かなくてすみます
- これで opensocial_app_url が取れました
- ここまでぐだぐだと書いてきましたが、手順が煩雑なのと、コンテナの実装に依存する部分があるので、微妙な気持ちになってきました
- あくまでも Twixi はこういうふうに作ったよ、ということで
- ではどうするかというと、以下のような流れのほうがすっきりするかも
- gadget.xml から gadgets.io.makeRequest() で st を外部サイトに送る
- 外部サイトは、opensocial_app_url を検証し、opensocial_viewer_id と st をセッションデータとして保存、それに紐付くトークンを生成しレスポンスに含めて返す
- gadget.xml から、返されたトークンをパラメータに含めて外部サイトに iframe 内のみリダイレクト
- 外部サイトでセッション用 cookie 発行、st を使って RESTful ウマー
- 次回、JavaScript API 使えないならマイミクの招待とかできないし OpenSocial の意味ぜんぜんないじゃん、と突っ込まれたときに、そこだけ最低限の JS を使ってなんとかする、という話を書きます
- つづく