Tender Surrender

本日米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 to [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オブジェクトのリクエストが可能に 新しく追加された@deletedセレクタとupdatedSinceパラメータを利用することで、指定された日時以降に削除されたコンタクトの取得が可能になりました。
  • 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フィールドをリストで返す/people/@supportedFieldsおよび/activities/@supportedFieldsというエンドポイントが定義されました。
  • 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...

PlaxoのJoseph Smarr氏が使う言葉に”Open Building Blocks for the Social Web”というものがあります。これはウェブをよりソーシャルにし、サービス相互の連携を深めていくために必要な”要素”を表しています。

この”要素”にはOpenID, OAuth, microformats, OpenSocialと、いずれもこのブログで取り上げてきたこれからのソーシャルウェブを占う重要な規格が挙げられていますが、そんな重要なピースのひとつに、Portable Contactsが加えられました。

Joseph Smarr氏の在籍するPlaxoにて、既に利用可能なAPIが公開されています。

Portable Contactsとは

Portable Contacts, is an easy-to-implement “people data” API that provides secure access to both traditional address book data and to modern social application data (profiles and friends lists).

PortableContactsとは、従来のアドレス帳データと最近のソーシャルアプリケーションデータ(プロフィールと友達リスト)のいずれにも、セキュアなアクセスを提供する、簡単に実装可能な”Peopleデータ”のAPIです。

現時点の仕様の中身を見てみると:

  • ディスカバリの方法(XRDS-Simple)
  • 認証/認可の方法(OAuth, Basic認証)
  • クエリパラメータ(ソート、フィルタ等)
  • 応答フォーマット(JSON, XML)
  • エラーコード
  • Contactのスキーマ

といった内容になっています。vCardやOpenSocial等、既存の仕様から大きく外れないよう意識して設計されているとのこと。

Portable Contactsの使いどころ

Portable Contactsはアドレス帳や友達リストを表すものですので、様々な分野で応用できることが予想されます。

ソーシャルネットワークサービス間の友達リスト交換

既にMySpaceのDataAvailabilityでサービスイメージが示されていますが、MySpaceの友達リストをTwitterにインポートする、なんてことが可能になります。

デスクトップアプリとのアドレス帳交換

例えばMac OS Xのアドレス帳アプリとMicrosoft Outlookのアドレス帳を、ウェブサービスを通じて同期するなんて事も、これまで以上に統一した規格の上で行う事ができるようになります。

携帯電話とSNSのアドレス帳を同期

自分が利用しているSNSの友達リストをそのまま携帯電話に乗せたり、その逆を行う事ができるようになります。ここでRipplexのようなサービスが間に入ると、さらに面白いことができるようになるでしょう。

OpenSocialとの関係

あれ、じゃあOpenSocialとPortable Contactsて同じじゃないの?と思った方もいるのではないでしょうか。そう、基本的にOpenSocialのPeople APIとPortable Contactsの役割は同じです。似た仕様が複数存在する事はあまり好ましくないため、個人的にも疑問に思っていました。

実はJoseph Smarr氏の働きかけにより、Portable ContactsはOpenSocial v0.8.1仕様で統合されました。言い換えると、OpenSocialのPeople APIの仕様とPortable Contactsの仕様は同じです。

OpenSocial v0.8.1の仕様はまもなく公開されると思いますが、内容はPortable Contactsに沿ったものになっていることが確認できます。

まとめ

ソーシャルウェブエコシステム構築の動きは、Portable Contactsのようなピースが揃う事でさらに加速してきています。今後もソーシャルウェブのメインプレイヤーたちの動向から目が離せません。

Read on...