- 改ざんされて困ってしまう OpenSocial JavaScript API ですが、実は、ガジェットがソーシャルデータを取得するときに、コンテナの RESTful API にアクセスをおこなっているのでした
- 通常、外部サーバから利用するための OpenSocial の RESTful API は OAuth でアクセス権限の制御をしますが
- JavaScript からアクセスする場合は、security token というものが用いられます
- ブラウザ上で OpenSocial JavaScript API から RESTful API が呼び出される様子
GET /social/data/people/@viewer/@friends?fields=id,name,thumbnailUrl&startIndex=0&count=1000&orderBy=topFriends&filterBy=all&networkDistance=&st=*** HTTP/1.1
Host: b2721bfb3ca713c9e377898ab19ade4d2ffb3a57.app0.mixi-platform.com
HTTP/1.x 200 OK
Content-Type: application/json
{"link":null,"entry":[{"thumbnailUrl":"http://profile.img.mixi.jp/xxx","nickname":"xxx","id":"xxx","updated":"2009-11-07T16:02:15Z","hasApp":"true"},...],"startIndex":0,"itemsPerPage":"1000","author":null,"totalResults":100}
- mixi は、現時点で OAuth の RESTful API をサポートしていませんが、JavaScript API を提供している OpenSocial コンテナには、既に security token による RESTful API が存在しているということになります
- 少なくとも shindig を採用しているところは
- ということなので Twixi では、ソーシャルデータの改ざんを防ぐため、外部サーバにアプリケーションを置き、そこから security token(以下st)を使用して RESTful API に直接アクセスすることにしました
- gadget.xml から shindig.auth.getSecurityToken() で st が取り出せるので、リダイレクトと同時に外部サーバに渡します
- このへんについては http://code.google.com/intl/ja/apis/friendconnect/opensocial_rest_rpc.html が詳しいのでどうぞ
<Content type="html" view="canvas"> <![CDATA[ <script type="text/javascript"> gadgets.util.registerOnLoadHandler(function(){ location.href = "http://twixi.dyndns.org/sample.cgi?st=" + encodeURIComponent(shindig.auth.getSecurityToken()); }); </script> ]]> </Content>
- 外部サーバ(perl の場合)
- ちょう便利なライブラリがあるので、渡された st を使ってマイミクの一覧などをゲットしましょう
- Net::OpenSocial::Client - OpenSocial REST/RPC Client - metacpan.org
use CGI; use Net::OpenSocial::Client; use Net::OpenSocial::Client::Container; use Net::OpenSocial::Client::Type::Auth qw(ST); use Net::OpenSocial::Client::Type::Protocol qw(REST); use Net::OpenSocial::Client::Type::Format qw(JSON); my $q = CGI->new; my $client = Net::OpenSocial::Client->new( container => Net::OpenSocial::Client::Container->new( rest_endpoint => q{http://app0.mixi-platform.com/social/data}, ), auth_type => ST, st => $q->param('st'), format_type => JSON, protocol_type => REST, ); print $q->header(-type => 'text/plain', -charset => 'utf-8'); my $person = $client->get_person('@viewer') or die $client->errstr; print 'viewer_id: ' . $person->get_field('id') . "\n"; print 'viewer_nickname: ' . $person->get_field('nickname') . "\n"; my $friends = $client->get_friends('@viewer') or die $client->errstr; for my $friend ( @{ $friends->items } ) { print 'friend_id: ' . $friend->get_field('id') . "\n"; print 'friend_nickname: ' . $friend->get_field('nickname') . "\n"; }
viewer_id: 11325239
viewer_nickname: あさんのう
friend_id: xxx
friend_nickname: xxx
...
-
- おめでとうございます!誰かの介入を受けることなく、ソーシャルデータを取得することができました
- もちろん、Activity を流したり、AppData をいじったりも可能です
- 外部サーバ(perl じゃない場合)
- OpenSocial Foundation Moves Standards Work to W3C Social Web Activity | W3C Blog
- 各言語の server-to-server な OpenSocial クライアントライブラリ
- 試してませんが、security token をサポートしているみたいなので、同じ要領で実装できると思います
- OpenSocial Foundation Moves Standards Work to W3C Social Web Activity | W3C Blog
- この方法を採用すると、当然、ガジェットの iframe の src は mixi と関係ない別のドメインになります
- 普通に、gadget.xml 内で st を外部サーバに gadgets.io.makeReqeust() で渡してもいいですが、アプリケーションをすべて外部に置きたかったので、このようになりました、以下理由
- st が URL のパラメーターとして渡されるので、referer などから漏れないように注意してください
- ガイドライン的にどうなの、という点ですが 駐車戦争 なども、がっつり http://mixi.linno.jp/parking/index とかになっているので、問題ないかと(多分)
- あと、JavaScript API がまったく使えなくなるので、opensocial.requestShareApp() とか使えなくなるけどどうすんの、という点については次回以降で解決策を書きます
- 外部サーバ上のアプリケーションでは、ユーザを識別するために上記の例にある viewer_id を使用します
- しかし、Twixi 以外のアプリに対して発行された st を渡されたとしても、viewer_id を取得できてしまう問題
- これを防ぐべく次回は、外部サーバ上でどのアプリに対して発行されたものか st を検証する方法の解説です