Facebook開発者向けドキュメントの日本語訳とTips

http://developers.facebook.com/docs/ に記載されているdocumentationの和訳と、調べていて分かったノウハウを紹介します。
Life is tough, so are we.
ドキュメント全体の目次はこちら
Facebook関連情報はFacebookページで共有しています。

ユーザ access_token の expires が返されないケース

概要

Facebook Page 管理系のアプリを作っている方には既知の問題かもしれませんが、先日、拙作の Facebook::OpenGraph について croak 'expires is not returned' という issue が追加されました。

本来の仕様では、/oauth/access_token エンドポイントからアクセストークンを取得した場合、それは最大でも約 60  日間で無効になることになっています。 その際に一緒に返されるのが expires で、開発者はこの値を見ることでトークンの有効期限を知ることができます。ところが、一定の条件を満たした場合はアクセストークンの期限が無期限になり、expires が返されないことがわかりました。

Facebook::OpenGraph のアクセストークン取得系メソッドでは access_token と expires が正しく返されることをチェックしているため、issue にある通りエラーになっていたのです。Facebook Platform にバグ報告したところ、これは望んでいる挙動ではないものの、現段階の動作としては正しいとの回答がありました。

前提

昔は offline_access パーミッションを取得することで、長期間利用可能なアクセストークンを取得することが可能でした。当時は通常のアクセストークンが 2 時間程度で切れてしまっていたため、ある程度長時間使うことが想定されるアプリや、夜間のバッチ処理でユーザの情報を取得したいアプリであれば、offline_access パーミッションを取得するのが一般的でした。
そのパーミッションは数年前に廃止され、代わりに最大約 60 日有効なアクセストークンを取得する手段が提供されました。この時点から、ユーザのアクセストークンは必ず有限であり、access_token と expires がセットで返される仕様になっています。

問題

今回報告されたケースでは、以下の手順でアクセストークンが無期限になり、expires が返されなくなることが確認できました。
  1. scope=manage_pages を指定した Login Dialog にユーザをリダイレクトする
  2. ユーザは manage_pages パーミッションを許可し、redirect_uri で定めた URL へ着地する
  3. 与えられた code パラメータを /oauth/access_token へ投げ、アクセストークンを取得する(この時点では expires も返される)
  4. expires が短期間であった場合、/oauth/access_token で 60 日間有効なトークンを取得する
  5. /{user-id}/accounts にアクセスし、ユーザが管理する Facebook Page のアクセストークンを得る(この時点でユーザのアクセストークンは無期限になる)
  6. デバッグツールでアクセストークンの詳細を調べ、無期限になっていることを確認する
    851591_750115185018891_1908473441_n
  7. ユーザを再度 Login Dialog に飛ばす
  8. 与えられた code パラメータを /oauth/access_token へ投げ、アクセストークンを取得する(expires は返されない)
このような動作は仕様にないため、常に expires が返される前提でチェックしている Facebook::OpenGraph ではエラーになります。そこで、Facebook Platform に「/oauth/access_token のドキュメント不備もしくは API のバグ」というチケットを登録して正式な回答を待ちました。
一点補足ですが、通常、上述のステップ 3 では短期間有効なアクセストークンのみ与えられ、それをもとに /{user-id}/accounts で Facebook Page 用のトークンを取得すると短期間のトークンのみが返されます。無期限の Page アクセストークンを得るには、必ずステップ 4 で長期間有効なユーザアクセストークンを取得しておく必要があります。が、今回確認したケースでは、manage_pages を要求した場合はステップ 3 の段階でも 60 日有効なトークンが返されました。

Facebook からの回答

回答によると、Facebook Page のトークンとユーザを関連付ける現在の実装上、この動作は正しいそうです。ただし、本来意図している動作ではないために、ドキュメントには明記されていないとのことでした。現実装の課題がクリアされれば access_token の期限は常に有限になり、 expires も返されるようになりそうな雰囲気です。また、Ads API を利用するアプリでも同様の挙動をするそうです。(回答中では、「expires が空文字列になったり 0 になる」と表現されていましたが、確認した限りでは expires というキー自体渡されません。)
access_token を無期限で使えるようにする裏ワザにもなりそうですが、回答の最後に「この目的のためだけに manage_pages を要求するのは認められていない」と念を押されました。4/30 の f8 以降、追加でパーミッションを要求する場合には Facebook Platform によるレビューを通らなければならないため、不必要な manage_pages を要求した場合はその段階で却下されるだろうと思います。

おまけ

ちょっと前から、Bug 詳細ページでユーザ名をマウスオーバーすると、そのユーザの Bug Karma や報告したバグ一覧、購読中のバグ一覧が表示されるようになりました。似たアプリを作っている開発者の報告したバグ等が探しやすくなりそうで良いですね。
が、下のキャプチャにある通り、一覧を表示しようとするとエラーになってしまいます。
10173493_777958702238030_524643995_n
というわけでこれもバグ報告したところ、Assigned になりました。バグ報告画面のバグ報告ってなんかシュール…

f8 2014 の発表: API バージョニングと注意点

4/30 に開催された f8 のキーノートでは、Facebook Platform が今後いかに安定して API を提供していくかについて、1) コア API の動作保証期間、2) API のバージョニング、 3) バグ報告への早期対応、という観点から発表がありましたので紹介します。

API の動作保証期間

これまでも Facebook Platform では頻繁に仕様変更が行われ、そのたびに開発者が悲鳴をあげていました。毎月、次の 90 日以内で対応し無くてはならない仕様変更が発表され、結果として毎月何かしらの対応を強いられていた次期や、そのペースが若干落ち着き、4 半期に一度の発表と翌 90 日間の対応となった時期などです。
2011 年の f8 に参加した際のレポートはここに書きましたが、この時の Open Graph Action と Object の発表によって、Facebook 内外を問わずユーザとその周りのあらゆるものを繋ぐという目標にだいぶ近づいたのではないかと思います。その影響もあってか、それ以前に比べれば仕様変更のペースも落ち着き、ドキュメントも整理され、プラットフォームとして成熟してきたような印象です。
そして昨日の f8 キーノートではついに、コア API は 2 年間動作を保証することが発表されました。 仕様変更の発表から 90 日の猶予期間しかない状態に比べれば、とても安心感があると思います。

API のバージョニング

こうして 2 年間は動作が保証されることになりましたが、その間にも新しい機能が追加されたり仕様が変更されるのは変わりません。それらの異なる仕様が共存できるよう、API がバージョニングされるようになりました。更新ログによれば、今回の f8 以前の仕様で動いているものが Version 1.0 や v1.0 と呼ばれ、それより後のものが Version 2.0 や v2.0 となります。今後は 2.1 や 2.2 などと増えていくようです。API にメジャーな変更があれば新しいバージョンが追加されます。

We're using the term 'Version 1.0' or 'v1.0' to talk about the APIs as they existed before we introduced versions, meaning before April 30, 2014 (the date of f8). 'Version 2.0' or 'v2.0' covers APIs that we are changing or launching at f8 2014. Later versions will be called 'Version 2.1', 'Version 2.2', and so on. They'll be launched whenever we make a breaking change to the API.

現行の v1.0 がサポートされるのは今後 1 年間のみですが、2.0 以降は先述の動作保証期間に従って 2 年間動作します。

10333112_605697729514600_969655318_n


バージョンの指定方法は一般的なもので、これまで /OBJECT_ID/CONNECTION_TYPE といった形式でエンドポイントを指定していたのが、/VERSION/OBJECT_ID/CONNECTION_TYPE 形式に変わるだけです。バージョンが指定されない場合は、その時点で提供されている最も古いバージョンの呼び出しとして扱われますので、既存のアプリを改修して今すぐバージョン指定しなくてはいけないというわけではありません。また、サポート期限の切れたバージョンを指定している場合も、サポートされているバージョンの中で最も古いバージョンの指定として扱われます。

851581_548985311885834_1878986979_n


ただ、ここで気をつけたいのが以下の文章です。

For apps that existed before April 30th 2014, making an API call without specifying a version number ('unversioned') is equivalent to making a call to the v1.0 of the API.
For apps created on or after April 30th 2014, making an API call without a specifing a version number is equivalent to making a call to v2.0 of the API.
2014-04-30 より前に登録されていたアプリであれば、バージョン指定をしない API 呼び出しは v1.0 利用とみなされます。それ以降の登録ならば v2.0 への呼び出しとして扱われます。

つまり、今の時点で新規にアプリ登録すると、呼び出し時にバージョン指定をしなくても v2.0 指定と同等になるということです。v1.0 のサポートが切れるまでの 1 年間は、v1.0 を利用しているつもりが実は v2.0 だった、ということが起こりえます。「バージョン指定がない場合はその時点の最も古いもの(v1.0)」とだけ覚えていると開発者コミュニティで質問していて話が合わないということになるので気をつけましょう。また、誰かの質問している現象が再現できない時など、いつ作成したアプリか聞いてみたら原因がわかるということもあるかもしれません。
新しいログインダイアログの発表にともなって、パーミッション周りや友達周りがすでに v2.0 で変更されているので要注意です。昨日以前に登録したアプリと、今日登録したアプリで /me/friends を叩くと結果が変わっているはずです。(v2.0 からは、アプリをインストールした友達しか返されません。)

バグ報告への早期対応

あともう一つ開発者にとって真新しい発表として、メジャーなバグであれば 48 時間以内に対応するというものがあります。最近バグ報告をした方なら実感があるかもしれませんが、去年や一昨年のバグ報告時よりも対応が早く、なおかつ丁寧になっています。
 以上の 3 つが 4 月中に私が報告したものです。以前であれば、「Thanks for report! We are looking into this.」のままアサインもされずに放置され、半年たってから CLOSE されたり TRIAGE に変えられたりという対応が多かったですが、今回の 3 件は 24 時間以内にレスポンスがあり、それが本当にバグであるか、どのように動作するのが正しいか、などをコメントしてくれています。お陰で、たとえアサインから解決まで数日かかろうとも、正しい挙動を知った上で待てるので少しは気が楽になります。

まとめ

というわけで、動作保証期間の明示や API のバージョニング、バグの早期対応などが整い、今後は今までより安定した環境が整うのではないかと思います。ただ今後 1 年間は、先述の通り、 API バージョンを指定しない場合の動作がアプリ登録時期によって変わるなどの例外があるので気をつけましょう。

開発者向け管理画面で見つけたキャラクター諸々と、私の近況

Facebook の developer リクエスト溜まっていたのを整理して 0 件状態にしたら、こんな画面が出てきました。意識してなかったんですが、前からだったんでしょうか。

facebook_beast

Facebook Messenger 初期のスタンプキャラクターで、ザックのペットでもある Beast や、以下のように Pusheen も居ます。

facebook_cat

あとは下のように見慣れないキャラクタも時々出ます。
これを期に、今まで放置してたリクエストを処理して何度かリロードしてみると楽しそうです。

faceboom_something

このブログは久しぶりの更新となりましたが、最近は Oklahomer's Blog というブログを作ってちょこちょこ更新してます。Facebook の英語情報を日本語で紹介しているだけだと、自分個人としては特に何も出来てないなというのがありまして。それで stackoverflow.com で英語圏の開発者とも関わろうとしてたんですが、コミュニティが大きいぶん、運よく自分で答えられそうな質問を見つけても他の人が先に答えてしまったりしていて、じゃぁ自分のペースで更新できるブログにするか、ということで英語のリハビリを兼ねてとりあえず blogger で始めました。
FQL でユーザのフリガナを取得する方法とか書こうとすると、日本語には漢字, ひらがな, カタカナの 3 種類があって、どれが表音文字でどれが違って。。。って話から説明が必要だったりで、そういうところが地味に大変ですね。
あと、ブログテンプレートの編集とか、やっぱり livedoor blog は使い勝手が良いなって改めて思いました。

続報:appsecret_proofパラメータの仕様公開

公式PHP SDKのGraph API問い合わせ部分の実装にappsecret_proofというパラメータが足され、アプリの設定画面からその利用・不利用設定ができるものの、仕様についてはどのドキュメントにも足されていないということを、以下のエントリで紹介してきました。
そこで、「Documentation for appsecret_proof parameter is missing(appsecret_proofパラメータのドキュメントが不足している)」というバグ報告をしていたのですが、ついに公式ドキュメントが追加され、公式ブログで周知されました。(バグ報告の方法については「ドキュメントの歩き方:FQL編」を参照)

公式ブログとドキュメントにはキャプチャやサンプルコードがあり、それらを見るだけで利用方法は分かるので、以下にざっくり全体像を紹介します。

概要

サーバサイドでGraph APIを利用する際のセキュリティ向上のため、API呼び出し時にappsecret_proofパラメータを足すことを必須にする。appsecret_proofパラメータの生成方法は後述。クライアントサイドからの利用時(connect-js)は不要。

アプリの設定

m0bO1
アプリの管理画面から、App Dashboard > Setting > Advanced > Securityと辿って行くと、Require AppSecret Proof for Server API callsという項目が見つかります。ここでEnabledを選択すれば、appsecret_proof無しでのAPI呼び出しができなくなります。

実装

あとは、リクエスト時にappsecret_proofパラメータを足してあげるだけ。
$appsecret_proof= hash_hmac('sha256', $access_token, $app_secret); 
curl \
  -F 'access_token=<access_token>' \
  -F 'appsecret_proof=<app secret proof>' \
  -F 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/friends?limit=50"}]' \
  https://graph.facebook.com

stackoverflow.com

facebook.stackoverflow.com上の回答も更新しておきました。

Facebook::OpenGraph:ソーシャルグラフとOpen Graphの変遷

Facebook::OpenGraphの1.00を出して1ヶ月ちょっと経ちましたが、モジュール名にOpen Graphという単語を使った為に、Open Graphアクションを用いる、いわゆるOpen Graphアプリのみに対応したモジュールに見えてしまうというのが気になっています。このエントリでは、Facebookのいうソーシャルグラフとは何か、初めてOpen Graphが公開された頃の定義は何か、そして2011年のアップデート以降のOpen Graphの定義がどうなっているのかを整理し、Facebook::OpenGraphという名称に決めた理由を説明します。

ソーシャルグラフ

Facebookが持つソーシャルグラフとその定義について、最初に公表されたのは2007年に開催されたf8でした。定義はその後のドキュメントにも書かれている通り、「人々や人々が周りの物事に対して持つコネクション(繋がり)」となります。Brad Fitzpatrick氏による定義「the global mapping of everybody and how they're related」と違い、人と人の関係だけでなく、人と物事の関係も含まれる点が特徴的です。
そのため、Facebookのソーシャルグラフを示す場合、それはfacebook.com上での人々の繋がりや、彼らがfacebook.com上でいいね!するなどして関わりを持った物事の繋がりを指します。それに対し、広義でFacebookのソーシャルに言及する際は、後述するOpen Graph ProtocolやOpen Graphアクション/オブジェクトによって、facebook.com外部で形成されてFacebookへ持ち込まれた繋がりも含まれます。

2010年当時のOpen Graph

Open Graphについては2010年のf8で最初に公表されました。この模様は「f8 Conference Keynote Speech - Recorded 21st April 2010」で視聴することができます。

散在するソーシャルグラフと、それらを繋いで生まれるOpen Graph

1回目のf8で紹介されたソーシャルグラフのコンセプトは、人や物事の持つ繋がりを全てマッピングできれば、相互に繋がった巨大なグラフが形成され、全ての人々が繋がっていることが分かるというものでした。しかし現実には、色々なサービスがソーシャルグラフの部分部分を形成しています。たとえばf8内で言及しているのは以下の通りです。
  • Facebookのソーシャルグラフは、人々の繋がり
  • Yelpのソーシャルグラフは、スモールビジネス関連
  • Pandora Radioのソーシャルグラフは、音楽関連
  • ニュースサイトのソーシャルグラフは、ニュースコンテント関連
これらのサービスが持つソーシャルグラフを繋ぐことができれば、webはもっとソーシャルで、パーソナライズされ、構造的に意味を持つものになるというのがf8での発表内容で、そうして繋がれたソーシャルグラフ群がOpen Graphです。

Open Graph Protocol

Open Graphを形成する上で最も重要なのがOGP(Open Graph Protocol)で、このメタタグは、任意のwebページが現実世界のどのオブジェクトを表すのかを定義します。これにより、FacebookユーザがOGPを埋め込んだwebページをいいね!した場合、ユーザが何をいいね!したのかという詳細情報がFacebookに伝わり、ユーザとオブジェクト間に繋がりが形成されます。
ユーザが自分の興味のある物をいいね!するという点では、facebook.com内なのか外なのかという違い以外、Facebookページをいいね!するのと何も代わりはありません。そのため、OGPを埋め込んだページにはFacebookページと同等の機能が与えられ、ステータス投稿などによって、いいね!したユーザのニュースフィードに対して更新情報を流せるようになっていました。
※現在、この機能は廃止されています。が、なぜか手書きでメモを取っていたノートが残っていたので、詳細はこちらをご覧ください。真ん中に居るのはホマ象くんです。リンク先で大きいサイズのを見られます。
名称未設定 0

Graph API

こうして外部の情報も取り込めるようにソーシャルグラフを拡張したものがOpen Graphで、そのグラフへアクセスする手段として発表されたのがGraph APIです。それまでのFacebook APIはLegacy APIとして残され、この時公開されたGraph APIが、いま私たちが使っているものです。
また、このブログでの和訳資料は2011年のf8以前のものが多く、このブログ中でOpen Graphと呼ぶ場合は、この当時の定義に従っている場合が多いです。(「Open Graphに触れる 1:基本」など)

2011年のOpen Graph

Open Graph アクションとオブジェクト

2011年9月のf8で、新しいOpen Graphのβ版が公開されました。2010年時点のOpen Graphでは、OGPによって表現できるオブジェクトの型は限られていましたし、それらオブジェクトに対してユーザが取れるアクションは、いいね!のみでした。
この新しいOpen Graphでは、OGPで表現できるオブジェクトの型をアプリ毎に定義できるようになり、オブジェクトに対して取れるアクションも、アプリで独自に定義できるようになりました。
  • 曲(オブジェクト)を聴いた(アクション)
  • クッキー(オブジェクト)を料理(アクション)した
  • 映画(オブジェクト)を視聴(アクション)した
など、現実世界での人と物事の繋がりを柔軟に表現できるようになり、以下のキャプチャのようなグラフが形成できるようになっています。

attachment

このf8の全体については、私のレポート「Facebook f8に参加してきました!」もご覧ください。

拡張部分の一人歩き

2011年はこれだけの変更だったと言ってしまえばこれだけです。アプリ毎にOGPを独自に拡張できるようになり、そのオブジェクトに対するアクションを、いいね!以外に独自定義できるというのが肝で、2010年に発表されたOpen Graphの延長上にあるのに変わりはありません。当時の公式ブログには以下のように発表されています。
In 2010, we extended the social graph, via the Open Graph protocol, to include websites and pages that people liked throughout the web. We are now extending the Open Graph to include other actions and objects created by apps and enabling these apps to integrate deeply into the Facebook experience.
2010年、私たちはソーシャルグラフを拡張し、Open Graph Protocolを利用することにより、人々がfacebook.com外部でいいね!したページをも取り込めるようにしました。そして今、アプリによって定義されたアクションやオブジェクトをOpen Graphに取り込めるように拡張し、それらアプリがFacebook体験に深く関われるようにしました。
当初、このOpen Graphアクションを実装したアプリを、FacebookはTimeline App(タイムラインアプリ)と呼んでいました。Open Graphアクションを投稿すると、それがユーザの行動としてタイムライン上に表示され、それが月単位や年単位で要約されるようになっていた為です。(のちにβ版のまま終わってしまうAdd To Timelineプラグインなど、Beaconの復活を思わせる機能を推していたのもあると思います。)
ただし、このとき発表されたタイムラインとOpen Graphアクションの連携が話題になったこともあり、色々なメディアでもOpen Graph拡張部分のみが伝えられ、新しいOpen Graphアクションを実装したアプリだけをOpen Graphアプリと呼ぶようになってしまいました。

現在

そういった影響もあって、今ではFacebook自身のドキュメントを見ていても、Open Graphと言えばOpen Graphアクションの実装を指す場合が多いようです。ただし、2010年当時からの厳密な定義に従えば、OGPによってfacebook.com外部の情報も取り込むようにソーシャルグラフを拡張したものがOpen Graphで、2011年のOpen Graphアクション・オブジェクトはその延長に過ぎません。
今現在も公式ドキュメントの片隅にその名残は残っていて、Graph APIのドキュメントでは以下のように紹介されています。
Everything in the Open Graph has an ID. You'll notice that the path that's selected is in the form /&lt;your facebook id&gt;. This is how you can make an API call that addresses any item in the graph that you have permission to reach. In the Graph API Explorer the results can contain links to other items.
Open Graph上の全てのものにはIDが振られています。 /ID の形式で指定したパスがそれを示していることに気付くでしょう。
851562_375695515876658_210317132_n
というわけで、私たちがいつも graph.facebook.com/ID で指定しているものはOpen Graph上のオブジェクトであり、ここでのIDはOpen Graph上のユニークIDであると分かります。というわけで、Open GraphにアクセスするGraph APIのクライアントモジュールということでFacebook::OpenGraphというモジュール名になっています。あとは、既存のモジュールでFacebook::Graphという名前が取られていたのが実は大きいです。。。
長くなりましたが、そういった理由から、Open Graphアクション周りにとどまらず、Field ExpansionBatch Request、 FQLFQL マルチクエリ、Open Graph Action投稿、Object API(日本語未訳)など、Graph APIが提供する様々な機能もサポートしていますので是非試してみてください。細かい用法についてはまた別の機会に解説しますが、まずは各メソッドのテストを見て頂くと分かるかと思います。
記事検索