ガジェットのOAuth認証 その2

今回もGoogle Code の Gadget API のページを参考にしながらOAuthについて。


ガジェットで OAuth を利用するには、XMLに以下の情報を含める必要がある。

  • サービスプロバイダ : OAuth による認証が可能な Web アプリケーション。
  • エンドポイント : 個人データにアクセスする際のURL。
  • セクション : ガジェットで使用するあらゆるサービスとエンドポイントの詳細を指定。セクション内に記述。
  • ユーザがデータへのアクセスを承認したかを判別するプログラム。
    • ユーザがアクセスを許可していない場合、ガジェットはユーザがサービスプロバイダにアクセスできる方法を提供する必要がある。
    • 例) サービスプロバイダの OAuth 認証 URL を指すリンクをユーザに表示する。その後、サービスプロバイダの手順にしたがって、ユーザは認証と承認を行う。ユーザが自分のデータへのアクセスを承認すると、ガジェットはユーザのデータにアクセスできるようになる。
  • makeRequest()関数の呼び出し。
  • 取得したデータを処理するコード。


これを念頭に置きながら、前回の記事で動かしたサンプルガジェットのソースを読んでみる。

サンプルガジェットはユーザの連絡先を取得して表示するもの。

セクション

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="OAuth Contacts" scrolling="true">
    <Require feature="opensocial-0.8" /> 
    <Require feature="locked-domain"/> 
    <OAuth>
      <Service name="google">
        <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> 
        <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.google.com/m8/feeds/" method="GET" /> 
        <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken?oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> 
      </Service>
    </OAuth>
  </ModulePrefs>
  •  : コンテナ(OAuth をサポートしている環境)と、ガジェットの OAuth サービス構成を記述する。
  •  : name はサービスの名前。実行時にこれを使用して OAuth サービスを参照する。
  •  : アクセストークンとリクエストトークンのURLを指定。また、タグのscopeに連絡先を取得するためのエンドポイント(Google Data Contacts のドキュメントを参照)のURLを指定。ここでは、"http://www.google.com/m8/feeds/"とする。
  •  : OAuth 認証 URL を指定。ガジェットがユーザデータにアクセスするのにそのユーザの承認を求める必要がある場合、この URL に対してポップアップウィンドウが開く。

Google の他のサービスからデータを取得する場合は、タグの scope に取得したいデータのエンドポイントを指定すればよさそう。

データの取得

function fetchData() {
  var params = {};
  url = "http://www.google.com/m8/feeds/contacts/default/base?alt=json";
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.OAUTH;
  params[gadgets.io.RequestParameters.OAUTH_SERVICE_NAME] = "google";
  params[gadgets.io.RequestParameters.OAUTH_USE_TOKEN] = "always";
  params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;

  gadgets.io.makeRequest(url, function (response) { 
    if (response.oauthApprovalUrl) {
      // Create the popup handler. The onOpen function is called when the user
      // opens the popup window. The onClose function is called when the popup
      // window is closed.
      var popup = shindig.oauth.popup({
        destination: response.oauthApprovalUrl,
        windowOptions: null,
        onOpen: function() { showOneSection('waiting'); },
        onClose: function() { fetchData(); }
      });
      // Use the popup handler to attach onclick handlers to UI elements.  The
      // createOpenerOnClick() function returns an onclick handler to open the
      // popup window.  The createApprovedOnClick function returns an onclick 
      // handler that will close the popup window and attempt to fetch the user's
      // data again.
      var personalize = document.getElementById('personalize');
      personalize.onclick = popup.createOpenerOnClick();
      var approvaldone = document.getElementById('approvaldone');
      approvaldone.onclick = popup.createApprovedOnClick();
      showOneSection('approval');
    } else if (response.data) {
      showOneSection('main');
      showResults(response.data);
    } else {
      // The response.oauthError and response.oauthErrorText values may help debug
      // problems with your gadget.
      var main = document.getElementById('main');
      var err = document.createTextNode('OAuth error: ' +
        response.oauthError + ': ' + response.oauthErrorText);
      main.appendChild(err);
      showOneSection('main');
    }
  }, params);
}

fetch()関数では、こちらの記事で書いた makeRequest()関数を呼び出す。

makeRequest()関数には urlcallbackopt_params が必要だった。

  • url :  Google Data Contacts のエンドポイントのURLを指定。
    • 以下のように、"?alt=json"と加えることでデータを JavaScript オブジェクトとして取得できる。
    • url = "http://www.google.com/m8/feeds/contacts/default/base?alt=json";
  • opt_params : OAuthに関するパラメータを記述。
  • callback : 以下で説明。

callback では

  1. response.oauthApprovalUrl を見る。
    • ユーザがユーザデータへのアクセスを許可していないとき、response.oauthApprovalUrl には URL が含まれる。
    • ユーザはこの URL にアクセスして、ガジェットによるデータアクセスを許可する必要がある。
  2. ガジェットは、ポップアップウィンドウを管理するための shindig.oauth.popup オブジェクトを作成する。
    • ユーザがリンクをクリックしてポップアップを開くときに、onOpen 関数が呼び出される。
    • ガジェットは showOneSection('waiting') を呼び出して適切なメッセージを表示し、ユーザがアクセスを承認するまで待機する。
    • ポップアップウィンドウを閉じるときに、onClose 関数が呼び出される。ポップアップウィンドウが閉じられると、ガジェットはユーザデータを取得するための fetchData() の呼び出しを登録する。
  3. 状況に応じて <div> の出力を変える。

認証に伴うガジェットへの表示

<div id="main" style="display: none">
  </div>

  <div id="approval" style="display: none">
    <img src="http://gadget-doc-examples.googlecode.com/svn/trunk/images/new.gif">
    <a href="#" id="personalize">Personalize this gadget</a>
  </div>

  <div id="waiting" style="display: none">
    Please click
    <a href="#" id="approvaldone">I've approved access</a>
    once you've approved access to your data.
  </div>

  <script type="text/javascript">
    function showOneSection(toshow) {
      var sections = [ 'main', 'approval', 'waiting' ];
      for (var i=0; i < sections.length; ++i) {
        var s = sections[i];
        var el = document.getElementById(s);
        if (s === toshow) {
          el.style.display = "block";
        } else {
          el.style.display = "none";
        }
      }
    }

ガジェットは <div> と showOneSection() 関数を使い、ガジェットの承認状態に基づいて3つの <div> によって表示を変える。

  • approval : ユーザがアクセスをまだ許可していない場合、ガジェットは approval <div> を使って、リクエストトークンを含む [Personalize this gadget] リンク付きの UI を表示する。ユーザはこのリンクをクリックして承認プロセスを開始する。
  • waiting : ユーザがポップアップウィンドウを開いてアクセスを承認するまで、ガジェットはこの <div> を表示する。ガジェットは、ユーザがデータへのアクセスを承認したことに対して確認を求めるメッセージを表示する。ユーザがアクセスを承認したことをガジェットが自動で検出できれば、ユーザーがこのリンクをクリックしなくても済むようにできるが、このリンクを表示しておくと、ユーザは自動検出が失敗したときもデータをフェッチできるようになる。自動検出が失敗した場合、ガジェットは「Please click I've approved access once you've approved access to your data.」というメッセージを表示する。ユーザがこれをクリックすると、ガジェットは fetchData() を呼び出してユーザデータをフェッチする。
  • main : アクセストークンが取得されると、ガジェットは実行されるたびに main <div> を使ってユーザデータを表示する。この <div> はエラーの表示にも使用される。


今回はGoogle Code の Gadget API のページをかなり引用してサンプルガジェットのソースを読んだ。
次回は、サンプルガジェットを元に、Google ドキュメントの一覧を表示するガジェットを作成する。