Tender Surrender

iGoogleはこれまで複数のガジェットを1ページに表示するスタイルでしたが、最近「canvasビュー」が追加され、1つのガジェットを画面いっぱいに表示して利用できるようになったことは記憶に新しいと思います。canvasビューを使うことで、特にGmailやGoogle Readerのガジェットでは、単体サービスのかなりの機能がガジェット上でそのまま利用できるようになり、大幅に利便性が向上しました。

このiGoogleの変化は、既に明言されてはいますが、iGoogleのOpenSocial対応を予感させ、将来的にGoogle全体がソーシャルネットワークになっていくことを示唆しています。実は既にGoogleがそれ自体をソーシャルネットワーク化していく方向性は随所に見られます。

Googleのソーシャル化

Gmail連絡先(コンタクトリスト)

ソーシャルネットワークを形作る上で最も重要になるソーシャルグラフを、GoogleはGmail/Google Talkに持ってきました。当然と言えば当然。この連絡先(コンタクトリスト)はAndroidケータイ上にもインポートされ、電話帳としても利用されており、いやでもリアルなソーシャルグラフになる点が特徴と言えます。

Google Mapsプロフィール

最近プライバシー問題で話題のGoogle Mapsには実はプロフィール機能がついており、画面上部の「プロフィール」リンクをクリックすると、自分のプロフィールを作成/表示することができます。これは後述のGoogleプロフィールと連携しています。

Google Readerの共有機能

Google ReaderはRSSリーダーですが、気になった記事をボタン一つで友達に共有できる機能があります。その際利用されるのがGmailの持つ連絡先のソーシャルグラフで、ここでも活用されています。

Googleプロフィール

いつのまにか、ひっそりと作られた感のあるのがGoogleプロフィールこれが今後どう充実して行くかは要注目です。

画面左上にユーザーの写真とニックネーム、住所が表示され、その下にはプロフィールの詳細情報が表示されます。今のところ住所や過去に住んだことのある場所、通った学校、勤めた会社、略歴に加え、Googleを使っても見つけられないもの、超能力(?)など一風変わった項目もあり、この画面から編集を行うことができます。

そして「リンク」。今のところ本当にただのリンクですが、利用している外部サービスを登録することができます。面白いのは、例えばFriendFeedを登録すると、自動的に他のサービスも登録候補にずらずらっと表示されるところ。なるほど、ここでGoogle Social Graph APIを活用しているようです。確かに、FriendFeedにはrel=”me”といったmicroformatが埋め込まれています。

メッセージ機能

Googleプロフィールに最近メッセージ機能が追加されました。英語版でしか存在を確認することはできませんが、プロフィールページからメッセージを送ることができるようです。これもOpenSocial対応を意識したものでしょう。

Googleは今後どう変わって行くのか

Googleがソーシャル化していく上で、今後どのような部分に変化が見られるのか予想してみました。

Googleプロフィールにガジェット

まず間違いなく、Googleプロフィールにもガジェットが追加できるようになるでしょう。

OpenSocialにはhomeビュー、canvasビュー、profileビュー、previewビューの4つがあらかじめ定義されていますが、ガジェット追加確認用のpreviewビューを除けば、一般的なSNSにおけるマイページ(homeビュー)、ガジェットのみを表示するcanvasビューが既にiGoogleで用意されているので、残りはプロフィールページ(profileビュー)となるのは自然な流れと言えます。

GoogleプロフィールのiGoogle統合

GoogleプロフィールとiGoogleの統合はあり得ない話ではありません。今もiGoogleのSandbox環境では自分のGoogleプロフィールの内容を確認することができますが、例えば簡単に画面遷移ができたりすることで、他者との距離を近づけ、iGoogleがソーシャルなものであることを意識できるようになるかもしれません。

アクティビティストリーム

iGoogleのSandboxでは既に片鱗が見えますが、OpenSocialのアクティビティストリームという機能がもう少し明確に、姿を現すはずです。アクティビティストリームとは、ユーザーの行動履歴のようなもので、mixiで言えば友達の日記やコミュニティの最新情報に当たります。

OpenSocialではガジェットからアクティビティを登録する機能が規定されていますが、iGoogleではこれに加えてリンクしたサービスのフィードも自動的に混ざる、FriendFeedライクな機能を追加してくるのではないでしょうか。MicrosoftがWindows Live Homeで追加した機能にも同様のものがあります。

まとめ

Googleプロフィールをネタに記事を書き始めたのですが、なんだかんだ話が広がり、結構大きい話になってしまいました。しかしGmailを中心として着実に、潜在的にソーシャルグラフを広げているGoogleが、完全なソーシャルネットワークの形態をとった時にどれほどの影響力を持ったものになるのか、正直想像もつきません。果たしてGmailを作った時点でここまで考えていたのか?今後の動向から目が離せません。

Read on...

本日米Yahoo!から、Yahoo! Open Strategy 1.0として、ディベロッパ向けにYahoo! Application Platform (YAP)Yahoo! Social Platform (YSP), Yahoo! Query Language (YQL)リリースされました。

Yahoo! Social Platform

プロフィールやアドレス帳、更新情報等、ソーシャルにまつわるAPIをRESTベースで提供するものです。認証機構にはOAuthを利用し、PHP版、Flash版のライブラリも提供されていますが、このREST APIはOpenSocial互換ではありません。

Yahoo! Query Language

SQLライクなコマンドを送信する事でYahoo! Pipesのようにデータ取得が可能なウェブベースのAPI。FacebookのFQLのようなもののようです。

Yahoo! Application Platform

Yahoo!上で動作する埋め込み型のアプリケーション。OpenSocialのガジェットプラットフォームは現時点ではサポートされていませんが、JavaScript APIは使えるようです。大きく2つのビューがあります。

Small View

HTMLまたはYML Liteのみサポート。JavaScriptはサポートされていません。YMLは、Facebookで言うところのFBMLのようなもので、 My!Yahoo等様々なページにパーツとして表示する事が想定されています。

Canvas View

**ディベロッパが指定したURLが出力したYMLをプロキシして表示するタイプのアプリケーション。Facebookライクな仕組みですね。もちろん、サーバーサイドでYahoo! Social Platformを使ったプログラムを書く事で、OAuthで認証を行い、RESTベースでソーシャルグラフを取得したり、コンタクトリストを取得したりすることできます。

また、OpenSocial JavaScript API(v0.8)にも対応しているので、クライアントサイドから更新情報を追加するといった利用も可能な様子。Cajaが利用されているので、セキュリティに気遣う事なく実装できそうです。(いつのまに実用レベルに達していたのでしょうか・・・)

時間のある時にでもサンプルアプリケーションを作ってみたいと思います。

所感

今回のYahoo!のリリースは、FacebookプラットフォームとOpenSocialのいいとこ取りといった感じ。ただし、OpenSocialに完全に準拠している訳ではないので、他で作ったアプリケーションをちょっとだけ書き換えて転用、という訳には行かなそうです。

例えば、クライアントからmakeRequestを使って外部サーバーのデータを取得するようなJavaScript APIは利用する事ができません。また、OpenSocialならHTMLを出力すればよかったものが、YMLを出力しなければなりません。等々・・(追記:Gadgets Core APIは利用できるようです。ただし、Pref、Viewなど、featureで指定する機能は利用できません。また、YMLは通常のHTMLに加え、独自タグを使って拡張した機能が使える、というもののようです。ただ、Caja対応のために外部スクリプトを読み込めないことが、他のコンテナに実装したガジェットをインポートする際の障壁になりそうです。)

ただ、世界最大のポータルサイトがOpenSocialに対応することの意義は大きく、今後の動きは要注目です。全体の戦略からすれば、OpenSocialの対応はあくまでパーツに過ぎず、今後のウェブのあり方を位置づける重要な意味を持ちます。先日行われたYahoo! Open Hack Dayのプレゼンテーションは必見です。

どんどんプラットフォーム化していくウェブと、その中で占めるソーシャル機能の持つ重要性が、日本でも認識される日はそう遠くないと思います。

Read on...

OpenSocial-Japanのメーリングリストで出した小ネタを貼っておきます。

OpenSocialアプリ(ガジェット)はiframe内に表示されているのですが、iframeタグのsrc属性に含まれるURLのquery部分に、実はソースコードとなるXMLのURLが書いてあります。 このブックマークレットを使えば、ワンクリックでソースコードを開くことができます。

Open Orkut Gadget XML

↑上記をブックマークレットとして保存し、Orkutアプリを表示した状態でクリックすると、ソースコードのページが新規ウィンドウで開きます。 (複数表示されている場合は、一番上のアプリのソースコードが開きます)

※Firefoxでしか動作確認してないので、動かなかったら教えてください。

Read on...

当ブログでこれまで何度かOpenSocialに絡んだOAuthについて取り上げてきましたが、MySpaceを参考にしていたため、署名方式としてHMAC-SHA1のみを対象にしてきました。しかしShindigを掘り下げる上でRSA-SHA1を避けて通ることはできず、むしろこちらについても十分な知識を得ていないとなかなか先に進めないことが分かりましたので、この機会にまとめてみます。(OpenSocialをある程度前提にしていますが、署名の話はOpenSocialに限らないものです。)

署名とは何か

ITの世界で署名とは、問い合わせ元がその人であることを証明するための手段、と言えます。OAuthだと、コンシューマがサービスプロバイダに対して、名乗っている通りの者であることを証明することを意味します。これは、「自分」もしくは「相手と自分」にしか分からないものをリクエストに付け加えて送ることで実現されます。

OAuthの仕様では、署名方式について厳密に規定していませんが、HMAC-SHA1、RSA-SHA1、PLAINTEXTの3つの署名方式を説明しています。

OAuth does not mandate a particular signature method, as each implementation can have its own unique requirements. The protocol defines three signature methods: HMAC-SHA1RSA-SHA1, and PLAINTEXT, but Service Providers are free to implement and document their own methods. Recommending any particular method is beyond the scope of this specification.

HMAC-SHA1

HMAC-SHA1を使ったOAuthでは、予めコンシューマとサービスプロバイダが、同じコンシューマキー(oauth_consumer_key)とコンシューマシークレット(oauth_consumer_secret)を持ちます。コンシューマシークレットはもちろん、秘密というくらいですから、2者以外に知られてはいけません。2者がコンシューマシークレットを共有することから、Shared Secretと呼んだりもします。

MySpaceでは、コンシューマキーをアプリケーションのURL、コンシューマシークレットをMD5らしきランダムな(?)ハッシュ文字列としていますが、コンシューマキーはディベロッパの任意で変更可能です。詳しくはこの辺りをご覧下さい。

RSA-SHA1

逆に、RSA-SHA1の方式では、コンシューマが公開鍵と秘密鍵を持ちますが、サービスプロバイダは秘密鍵を知ることはありません。コンシューマは秘密鍵で暗号化した署名を加えたリクエストを投げます。この暗号化された署名は、公開鍵でしか解くことができませんし、秘密鍵でしか作ることができないため、コンシューマが身分を証明できる、という訳です。

署名を作る際、HMAC-SHA1方式の場合、コンシューマシークレット(oauth_consumer_secret)とトークンシークレット(oauth_token_secret)を”&”で繋いだものをkeyとして利用しますが、RSA-SHA1方式の場合、秘密鍵をkeyとして使って暗号化します。そのため、コンシューマシークレットとトークンシークレットは不要です。

逆にサービスプロバイダは、公開鍵を使って署名が正当なものであることを確認します。

$publickeyid = openssl_get_publickey($cert);
$ok = openssl_verify($raw, $signature, $publickeyid);
openssl_free_key($publickeyid);

$certは公開鍵、$rawは署名の基本文字列(Signature Base String)、$signatureは署名文字列(oauth_signature)を表しています。$rawと$signatureはコンシューマからのリクエストで生成することができますが、$certについてはちょっと考察が必要です。

RSA-SHA1の公開鍵の扱い

OAuthの拡張としてOAuth Key Rotation Extensionが提案されています。これはコンシューマがサービスプロバイダにリクエストする際、公開鍵のIDをリクエストと一緒に渡すことで、サービスプロバイダに鍵をダウンロード/認識させるための仕様です。公開鍵のIDはxoauth_signature_publickeyパラメータで渡されます

OAuth Key Rotation Extensionのドラフト、OpenSocial/Gadgetの仕様書など、いくつかのドキュメントにxoauth_public_keyと記述されていますが、Shindigの実装でxoauth_signature_publickeyが使用されており、こちらが正式なものとなるようです。

ここで公開鍵のIDと言いましたが、もちろん、これだけでは公開鍵を取得することができないので、これを使ってゴニョゴニョする必要があります。

が、、、。

OpenSocial/Gadgetの仕様書には

The container should make its public key available for download at a well-known location. The location https://<em>container-hostname</em>/opensocial/certificates/<em>xoauth_public_keyvalue</em> is recommended.

と書いてあるのですが、Shindigの実装ではhttp://container-hostname/public.cerになっていたりと、仕様が一貫していません。

現実はどうしているかというと、xoauth_signature_publickeyを無視して、コンテナのドキュメントに書いてある公開鍵をコピペしてソースコードにハードコーディングしています。hi5、Orkutについては動作確認ができました。iGoogleについてはここに公開鍵が書いてありますが、動作しませんでした。

OAuthが広まって様々なコンシューマが登場するまでは、まだまだこの中途半端な状態が続くのではないでしょうか。

コンシューマは誰か

ここで勘のいい方は気付かれたと思いますが、RSA-SHA1方式の場合、署名元がOpenSocialのコンテナサイトそのものになっています。MySpaceのように、ガジェットではありません。ということは、もちろんコンシューマキー(oauth_consumer_key)もOrkutなら”orkut.com”、hi5なら”hi5.com”といった具合に、コンテナサイトを表すものが使用されます。

またこの方式の場合、どのガジェットがリクエストを投げているのかを表すため、xoauth_app_urlというパラメータが追加されます。これを提案しているのがOAuth Gadget Extensionです。

MySpaceのようにHMAC-SHA1を使っている場合は、ガジェットごとにコンシューマキーを設定し、ガジェットのリクエストをコンテナがProxyするという形を取っていました。これはShindigを使っているiGoogle、Orkut、hi5と、独自にOpenSocialを実装しているMySpaceとの方針の違いから来るものです。

HMAC-SHA1方式でコンテナをコンシューマとして扱おうとすると、シークレットは2者間のみで共有されなければならないため、コンシューマは、サービスプロバイダごとにキーとシークレットを発行しなければなりません。しかし、RSA-SHA1方式であれば、コンテナがコンシューマでも、公開鍵と秘密鍵の組み合わせは一つだけあれば使い回せるため、OpenSocialにおけるmakeRequest (Outbound OAuth)のように、コンテナが外部サービスからデータを取得するアーキテクチャの場合、RSA-SHA1方式にした方がコンシューマにとってサービスプロバイダの追加も容易になりますし、サービスプロバイダにとってコンシューマの署名を確認する作業も楽になるのが利点です。

ShindigがRSA-SHA1方式を中心に実装されているのはそんな理由がありそうです。ちなみに、Shindigの開発はGoogleが中心になって行われており、HMAC-SHA1方式についても現在実装中らしいですが、iGoogleでのコンシューマキーとコンシューマシークレットの発行は、メールで依頼することになっているため、今のところ本気で考えてはいなさそうです。

In the case of the iGoogle sandbox, you can send mail [email protected] with the following information to register your shared secret:
* URL of your gadget
* The shared secret assigned to you by the service provider
* The consumer key assigned to you by the service provider
* Whether to use symmetric or asymmetric signing with the service provider (or say that you don’t know)
Until your shared secret has been registered, your gadget will not work.  If you change the URL of your gadget, you will need to re-register the secret for that gadget.

まとめ

現時点ではOpenSocialのOutbound OAuthではMySpaceがHMAC-SHA1方式でガジェットをコンシューマに、Shindig系コンテナはRSA-SHA1方式でコンテナをコンシューマにしていますので、外部サーバーとやり取りを多なうOpenSocialガジェットを作る場合、どちらからのリクエストも受け付けられるよう構築しておく必要がありそうです。

参考サイト

Read on...

OpenSocial v0.8.1仕様が公開されました。

※翻訳については一部ベータ版からの修正内容が反映されていない箇所があります。誤りを見つけた際はご指摘ください。

リリースノートは下記の通り:

OpenSocialリリースノート

OpenSocialの仕様変更点

  • サーバーサイドAPIの変更 サーバー間通信機能に、よりシンプルなバッチ処理を可能とするJSON RPCプロトコルが追加されました。名前の一貫性を保つため、RESTful APIは今後RESTfulプロトコルと呼ばれます。
  • **OpenSocial IDで許可する文字に”-”, “”, “.”を追加** OpenSocial IDは従来の英数字に加え、”-”, “”, および”.”を含むことができます。
  • Portable Contacts仕様にアライン

**互換性のない変更点
**

  • **RESTfulプロトコルの非互換性 **RESTfulプロトコルから多くのクエリやレスポンスフィールドが名称変更/削除されました。RESTfulプロトコルの変更点全てを下記に示します。

RESTfulプロトコルの変更点

  • PortableContactsとの互換性 RESTfulプロトコルを実装することで、コンテナはPortableContacts仕様と技術的互換性を持つことになります。下記の変更点はこの互換性実現のために実装されました。
  • 新しいレスポンス型format=xml リクエストがformat=xmlパラメータをサポートするようになりました。Peopleのリクエストはformat=xmlかformat=jsonで行われなければなりません。
  • コンテナはランダムアクセスなページングを実装しなければならない コンテナはstartIndexとitemsPerPageパラメータを使ったページングの実装が必須となりました。
  • コレクションのフィールドからrel=nextリンクが廃止 このパラメータはJSONコレクションレスポンスから削除されました
  • コレクションのフィールドからauthorが廃止 このパラメータはJSONコレクションレスポンスから削除されました
  • コンテナは全てのコンタクトを一度に返せなければならない コンテナは一度のリクエストで全てのコンタクトを返すことができなければなりませんが、パフォーマンス上の理由から返すコンタクトの数に上限を設けることができます。
  • itemsPerPageのデフォルト値 itemsPerPageパラメータがリクエストで指定されていない場合のデフォルト値はコンテナに依存します。
  • ソートパラメータの変更点 orderByパラメータはsortByに名称変更されました。また、sortOrderパラメータが追加され、ascending(昇順)とdescending(降順)を与えることができます。デフォルトはascendingです。
  • updatedSinceパラメータの追加 クエリで、指定された期間内に更新されたエントリのみを返すよう指定することができます。
  • ソートおよびフィルタリングが行われたかをレスポンスに表示 ソートやフィルタリングはコンテナにとってコストが高いため、実際にリクエストと同じ内容のフィルタリングが行われたかを示す、トップレベルのレスポンスフィールドfiltered, sorted, updatedSinceがレスポンスに含まれるようになりました
  • 削除されたPersonオブジェクトのリクエストが可能に [email protected][email protected][email protected]
  • Personレスポンスは最低でもidとnameフィールドを含まなければならない コンテナはnameおよびidフィールドをPersonデータに含まなければなりません。
  • profile URLはURLでもなければならない PersonのprofileUrlフィールドで返される値はtypeがprofileのエントリのurlsフィールドでも返されなければなりません。
  • Personにphotosフィールド追加 Personにurl, type, primaryサブフィールドを持ったエントリのリストを含む、photosフィールドが追加されました。PersonオブジェクトでthumbnailUrlフィールドが返された場合、このurlはtypeがthumbnailであるエントリのphotosフィールドにも存在しなければなりません。
  • Personにimsフィールド追加 Personにvalue, type, primaryのサブフィールドを持ったimsフィールドが追加されました。type値としてよく使用される“aim”, “gtalk”, “icq”, “xmpp”, “msn”, “skype”, “qq”, “yahoo”が定義されていますが、新しいtypeを定義することもできます。
  • Personにaccountsフィールド追加 Personにその人がアカウントを所有する他のサービスを表すaccountsフィールドが追加されました。このフィールドはdomain, userid, username, primaryサブフィールドを持ったエントリのリストを含みます。
  • Personの複数フィールドにprimaryサブフィールド追加 Personのemails, urls, ims, phoneNumbers, addresses, organizations, photosフィールドに、リスト中どのフィールドが主たるものか(存在する場合のみ)を示すprimaryサブフィールドが追加されました。
  • jobsおよびschoolsの複数フィールドをorganizationsに統合 jobsおよびschoolsのエントリはorganizationsという名前のOrganization構造の配列にまとめられました。Organization構造は”job”、”school”を正規値とするtypeサブフィールドで拡張されます。
  • Personの複数フィールドをvalueフィールドに標準化 Personの複数フィールドで主となるテキスト値はvalueというサブフィールドに保存されるべきです。これはemails.address, phoneNumbers.number, urls.addressおよびすべての{Enum}.keyフィールドのインスタンスを{Enum}.valueに名称変更することが必要となります。addresses, accounts, organizationsフィールドは複雑なため、valueフィールドのコンセプトが存在しません。ソートやフィルタリングを行うため、これらのフィールドの”主たる”サブフィールドに該当する部分は、addresses.formatted, accounts.domain, and organizations.nameとなります。
  • Person.genderフィールドは文字列に Personではgenderを文字列フィールドとして扱い、”male”および”female”を正規値とします。
  • AddressesからextendedAddressまたはpoBoxサブフィールドが廃止 streetAddressサブフィールドに完全な(複数行の場合もある)住所を保存することができるようになったため、AddressサブフィールドのextendedAddressおよびpoBoxが廃止されました。
  • unstructuredAddressをformattedに変更 AddressのunstructuredAddressサブフィールドはformattedに名称変更されました。
  • dateOfBirthをbirthdayに変更 PersonのdateOfBirthフィールドはbirthdayに名称変更されました。
  • timeZoneをutcOffsetに変更 PersonのtimeZoneフィールドはutcOffsetに名称変更されました。
  • nicknameの定義 Personのnicknameフィールドは現実世界でこの人物を指すくだけた方法”と定義されました。
  • Personフィールドのデフォルトセット Personリクエストでクエリパラメータfieldsがない場合、JS APIのデフォルトと一致させるため、最小限必要とされるデフォルトセットとしてid, name, thumbnailUrlが定義されました。
  • supportedFieldsのクエリ RESTfulプロトコルにコンテナがサポートするPersonおよびActivityフィールドをリストで返す[email protected][email protected]されました。
  • indexByの廃止 indexByクエリパラメータは廃止されました。
  • Activity.titleフィールドはHTML文字列に Activityタイトルフィールドは複雑なデータオブジェクトではなく、HTMLマークアップを含む文字列として扱われるようになります。
  • unstructuredをformattedに変更 名前フィールドのunstructuredはformattedに変更されました。
  • displayNameフィールドを追加 PersonフィールドのトップレベルフールドとしてdisplayNameが追加されました。

RPCプロトコルの変更点

  • RPCプロトコルが登場 バッチ処理や複雑なサーバー間処理を簡易化するためのオプションとして、新しくRPCプロトコルが登場しました。

opensocial.* JavaScriptの変更点

  • 新しいopensocial.IdSpec.GroupId enum IdSpecオブジェクトを構成するため、opensocial.IdSpec.GroupId.FRIENDSまたはopensocial.IdSpec.GroupId.SELFを使用することができます。
  • supportsFieldのレスポンスを定義 opensocial.Environment.supportsField()の戻り値として、コンテナがフィールドをサポートする場合はtrue、そうでない場合はfalseを返すことが定義されました。

gadgets.* JavaScriptの変更点

  • gadgets.* JavaScript APIに変更点はありません。

Gadgets XMLの変更点

  • **要素でOAuthをサポート** 要素のauthz属性で”oauth”値がサポートされるようになりました。</span>authzがoauthの場合、oauth_service_name, oauth_token_name, oauth_request_token, oauth_request_token_secret属性が取得されます。これらの属性はgadgets.io.makeRequestパラメータに一致するものと同様の意味とデフォルト値を持ちます。

Read on...