このドキュメントでは、OAuth 機能を使って認証を行うガジェットの作成方法について説明します。OAuth は makeRequest() 関数と組み合わせて使用します。makeRequest() 関数を使用してリモート コンテンツをフェッチする方法については、リモート コンテンツのフェッチをご覧ください。
このドキュメントでは最も簡単なユース ケースに焦点を当てます。 つまり、iGoogle 上で実行するガジェットを作成し、OAuth プロトコルをサポートする任意のウェブサイトからユーザーの個人データにアクセスするシナリオです。ただし、これは OAuth の使用方法の 1 つでしかありません。最終的に、コンテナ上で実行されるあらゆる OpenSocial ガジェットは、このドキュメントで説明されている手法を使って、OAuth 保護されたデータにアクセスできます。iGoogle はコンテナとして最も簡単なモデルを提供します。それは、ユーザーが iGoogle に追加したガジェットはそのユーザーだけに表示されるためです。ソーシャル ネットワーク コンテナでますます複雑になっていることは、ガジェットを参照するユーザーがガジェットを追加したデータ所有者と同一ではない場合があることです。サービス プロバイダがソーシャル ネットワーク コンテナの OAuth をサポートする方法について詳しくは、ドキュメント OAuth Enabled Gadgets on OpenSocial enabled Social Networks をご覧ください。
多くのインターネット サービスが REST API の提供を開始しています。この API を使えば、これらのインターネット サービスがユーザーに代わって保管している個人データにアクセスできます。たとえばインターネット サービスは、ユーザーに写真、メール、アドレス帳、健康記録などへのアクセスを提供することができます。OAuth は、個人データのアカウント所有者がホスティング サービスに指示して、別のウェブサイト (またはガジェット) が個人データにアクセスできるようにするための標準規格です。OAuth プロキシは、ガジェットが OAuth 標準規格を簡単に使用できるよう設計されています。
注: OAuth プロキシは、OpenSocial コンテナ内で実行するガジェットの gadgets.* API でのみサポートされます。これはレガシー Gadgets API ではサポートされません。現在、iGoogle はこの機能をサポートするガジェットのコンテナとなっています。ただし、ガジェット仕様と OAuth プロキシの実装である Shindig と呼ばれるオープン ソース プロジェクトがあります。この技術の展開については、他の多くのインターネット ウェブサイトで評価が行われています。
このドキュメントは、OAuth プロトコルを使用してユーザーのサービスと通信したいとお考えのガジェットのデベロッパーを対象としています。また、読者は利用するするサービスに精通し、関連するアクセス/認証の問題を理解していことを前提としています。ガジェットの認証プロキシ サービスを使用する際には、サービス固有の情報をある程度理解している必要があります。
OAuth は、Google で使用可能なすべての REST API (ウェブ アプリケーション用の OAuth 認証と Google Data API のドキュメントをご覧ください) と MySpace の Data Availability API でサポートされます。OAuth コミュニティの wiki には、OAuth 対応の API を提供する追加のサービス プロバイダが掲載されています。
OAuth の基本的な用語の定義を次の表に示します。詳しくは、OAuth 仕様とウェブ アプリケーション用の OAuth 認証をご覧ください。
| 用語 | 定義 |
|---|---|
| サービス プロバイダ | OAuth を使ったアクセスを可能にするウェブ アプリケーションです。たとえば Google や MySpace などがあります。 |
| ユーザー | サービス プロバイダのアカウントを持つ個人です。サービス プロバイダは、OAuth 経由でアクセス可能な、この個人のデータを保有できます。たとえばガジェットはユーザーの Google カレンダーのデータに OAuth 経由でアクセスできます。 |
| コンシューマ | OAuth を使って、ユーザーに代わってサービス プロバイダにアクセスするウェブサイトまたはアプリケーションです。OAuth を使ってユーザー データにアクセスするガジェットは、この意味でコンシューマになります。 |
| 保護されたリソース | サービス プロバイダが制御するデータです。コンシューマ (ガジェット) は認証を通してこのデータにアクセスできます。 |
| コンテナ | コンテナとは、ガジェットの組み込み先である OpenSocial 環境です。たとえば iGoogle はコンテナです。コンテナはガジェットのレイアウトとコントロールを管理すると共に、ガジェットに代わってさまざまな機能をサポートします。OAuth ガジェットは OAuth をサポートするコンテナでのみ実行できます。ガジェットが OAuth を使用する場合、プロトコルで必要なすべてのデジタル署名を処理し、OAuth プロトコルをガジェットに代わって実際に実行するのはコンテナです。 |
| コンシューマ キー |
ガジェットが自身をサービス プロバイダに識別させるために使用する値です。これは oauth_consumer_key パラメータに対応します。詳しくは、OAuth 仕様をご覧ください。 |
| コンシューマ シークレット | ガジェットがコンシューマ キーの所有権を確立するために使用するシークレットです。 |
| リクエスト トークン | ガジェットがユーザーから許可を取得するために使用する値であり、アクセス トークンと交換されます。 |
| アクセス トークン | ガジェットが、ユーザーのサービス プロバイダ認証情報を使用しないで、保護されたリソースにユーザーに代わってアクセスするために使用する値です。 |
| トークン シークレット | ガジェットが特定のトークンの所有権を確立するために使用するシークレットです。 |
たとえばユーザーの個人用カレンダー データに Google Data API 経由でアクセスするガジェットを持っているとします。この場合、Google はサービス プロバイダであり、ガジェットはコンシューマです。ユーザーは、ガジェットを使って個人用のカレンダー データにアクセスする個人です。
ユーザーが初めてガジェットを実行すると、ガジェットはユーザーをサービス プロバイダのサイトに送ります。そのサイトでユーザーは、ユーザーのカレンダー データにアクセスするための許可をガジェットに与えるよう求められます。この認証は OAuth で処理されます。ユーザーが Google アカウントにログインして、ガジェットに許可を与えると、ガジェットはその時点から (ユーザーが明示的に許可を無効にするまで) ユーザーのカレンダー データにアクセスできるようになります。ユーザーはガジェットを使って自分のデータにアクセスするのに再度ログインして許可を与える必要はありません。
OAuth ガジェットを作成する最初の手順はサービス プロバイダの選択です。OAuth では 2 つのユース ケースがあります。
以降では、この 2 つのオプションについて詳しく説明します。
Google Data API にアクセスする場合に必要な作業は、アクセスする Google Data REST API エンドポイントを指定することだけです。エンドポイントは、<OAuth> セクション (<ModulePrefs> セクションの下) 内と、そのエンドポイントを使ってデータを要求するガジェットのコード内に指定します。
通常、Google 以外のエンドポイントにアクセスするには、アプリケーションを Google 以外のサービス プロバイダに登録する必要があります (たとえば MySpace 登録をご覧ください)。あなたの企業が独自の OAuth サービス プロバイダのエンドポイントを公開する場合は、それを企業で作成するガジェットのみで使用する場合であっても、Google が提供する OAuth の高度な技法に関するサイトをご覧になることをおすすめします。
アプリケーションを Google 以外のサービス プロバイダに登録すると、そのプロバイダから OAuth コンシューマ シークレットが提供されます。ユーザーはこれを使って、アプリケーションからサービス プロバイダへのすべての要求にデジタル署名します。ガジェットは一般に公開されます。したがって、ガジェットはこのような種類のシークレットを保管するのに適切な場所ではありません。代わりとして、ガジェットを実行するコンテナを提供するウェブサイトが OAuth プロキシを提供する場合、そのウェブサイトに OAuth コンシューマ シークレットを登録できます。
iGoogle の場合、次の情報を含めたメールを oauthproxyreg@google.com に送れば、OAuth コンシューマ シークレットを登録できます。
OAuth コンシューマ シークレットの登録が完了するまで、ガジェットは動作しません。ガジェットの URL を変更する場合、そのガジェットのシークレットを再登録する必要があります。
OAuth コンシューマ キーやコンシューマ シークレットを要求する場合、多くの OAuth サービス プロバイダから OAuth コールバック URL の提示を要求されます。ガジェットのコールバック URL http://oauth.gmodules.com/gadgets/oauthcallback を指定できます。
開発コミュニティがこの手動の登録手順を行わなくても済むようにするには、デジタル署名を iGoogle から直接受け付けるように OAuth 構成を拡張できます。現在、iGoogle は RSA_SHA1 署名方式 (OAuth 標準規格で定義される) と次の公開鍵を使用します。ここでは、さまざまなプログラム言語で実装された OAuth ライブラリに簡単にインポートされる必要のある自己署名証明書として示されています。
-----BEGIN CERTIFICATE-----
MIIDBDCCAm2gAwIBAgIJAK8dGINfkSTHMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzETMBEG
A1UEChMKR29vZ2xlIEluYzEXMBUGA1UEAxMOd3d3Lmdvb2dsZS5jb20wHhcNMDgx
MDA4MDEwODMyWhcNMDkxMDA4MDEwODMyWjBgMQswCQYDVQQGEwJVUzELMAkGA1UE
CBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEzARBgNVBAoTCkdvb2dsZSBJ
bmMxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDQUV7ukIfIixbokHONGMW9+ed0E9X4m99I8upPQp3iAtqIvWs7XCbA
bGqzQH1qX9Y00hrQ5RRQj8OI3tRiQs/KfzGWOdvLpIk5oXpdT58tg4FlYh5fbhIo
VoVn4GvtSjKmJFsoM8NRtEJHL1aWd++dXzkQjEsNcBXwQvfDb0YnbQIDAQABo4HF
MIHCMB0GA1UdDgQWBBSm/h1pNY91bNfW08ac9riYzs3cxzCBkgYDVR0jBIGKMIGH
gBSm/h1pNY91bNfW08ac9riYzs3cx6FkpGIwYDELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUg
SW5jMRcwFQYDVQQDEw53d3cuZ29vZ2xlLmNvbYIJAK8dGINfkSTHMAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAYpHTr3vQNsHHHUm4MkYcDB20a5KvcFoX
gCcYtmdyd8rh/FKeZm2me7eQCXgBfJqQ4dvVLJ4LgIQiU3R5ZDe0WbW7rJ3M9ADQ
FyQoRJP8OIMYW3BoMi0Z4E730KSLRh6kfLq4rK6vw7lkH9oynaHHWZSJLDAp17cP
j+6znWkN9/g=
-----END CERTIFICATE-----
iGoogle はドラフト版の OAuth ガジェット拡張を使って、サービス プロバイダへの要求を他に頼るガジェットの URL を提供します。
エンドポイントとは、ガジェットがサービス プロバイダ経由で個人データにアクセスする際に使用する URL です。使用可能なエンドポイントについては、サービス プロバイダのドキュメントをご覧ください。Google Data API をサポートする Google サービスを使ってガジェットがデータを要求する場合は、Google Data API の各種ドキュメントを参照して各サービスでサポートされるエンドポイントを確認してください。エンドポイントによっては認証 (OAuth を使う認証) が必要なものと必要でないものがあります。Google Data エンドポイントの例を次にいくつか示します。
http://www.google.com/m8/feeds/contacts/default/full/ -- 現在ログインしているユーザーの連絡先を含むフィードを取得します。http://gdata.youtube.com/feeds/api/users/default/uploads?alt=json -- 現在ログインしているユーザーのアップロード済みの YouTube 動画を含む JSON 形式のフィードを取得します。http://gdata.youtube.com/feeds/api/users/username/uploads -- username に指定されたユーザーの YouTube 動画を含むフィードを取得します。この場合、認証は必要ありません。 ガジェットは特定のスコープ下でのみデータにアクセスできます。ガジェットが scope=http://www.google.com/m8/feeds/ へのアクセスを要求する場合、そのガジェットは Contacts API からのエンドポイント (フィード) のみを使用できます。1 つのガジェットは複数のスコープを要求できます。
簡単なガジェットの例を使って OAuth ガジェットがどのように動作するかを説明します。このサンプル ガジェットは現在ログインしているユーザーの連絡先をフェッチして表示します。次の手順にそって OAuth ガジェットの動作の感触をつかんでください。
OAuth ガジェットは gadgets.* API に基づく必要があるため、OAuth をサポートする OpenSocial コンテナ内で実行する必要があります。OAuth ガジェットを iGoogle 内に展開することができます。
ガジェットを iGoogle に追加するには:
新しく追加されたサンプル ガジェットには、[Personalize this gadget] というリンクが表示されます。このリンクにはリクエスト トークンが含まれます。次の手順に従ってあなたのデータへのアクセスを許可します。
ガジェットを削除するか、[Google アカウント] ページでアクセスを無効にしない限り、この時点からガジェットはあなたのデータに引き続きアクセスすることができます。アクセスを許可する必要があるのは 1 度だけです。
このサンプル ガジェットは、承認プロセスを体験するための 1 つの方法を示します。ユーザーの実装に関係なく、ガジェットでは次の処理が必要です。
Shindig プロジェクトでは、ポップアップ ウィンドウを作成できる JavaScript ライブラリや、ポップアップ ウィンドウが閉じられたことを検出できる JavaScript ライブラリが提供されています。このトピックに関して詳しくは、承認フローの実装をご覧ください。
必要なデータをフェッチするために使用するサービス プロバイダとエンドポイントを決定したら、ガジェットの実装をいつでも開始できます。
通常のガジェット機能に加えて、OAuth ガジェットには次の情報を含める必要があります。
<OAuth...> セクション。これはガジェットの <ModulePrefs> セクション内に指定します。gadgets.* makeRequest() 関数の呼び出し。ここでは、OAuth がどのように動作するかを理解するためにサンプル ガジェットのセクションを 1 つずつ詳しく見ていきます。
このサンプル ガジェットは Google Contacts Data API を使って、現在ログインしているユーザーの連絡先をフェッチします。このサンプル ガジェットはエンドポイント http://www.google.com/m8/feeds/contacts/default/full を使用して、要求に付加された資格情報を持つユーザーの連絡先を返すようサーバーに指示します。連絡先情報は、JSON 形式の ATOM XML 結果 (http://www.google.com/m8/feeds/contacts/default/full?alt=json) として返されます。詳しくは、Using JSON with Google Data APIs をご覧ください。
ガジェットの完全なコードは次のとおりです。以降でこのガジェットの詳細を説明します。
<?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>
<Content type="html">
<![CDATA[
<!-- shindig oauth popup handling code -->
<script src="http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/popup.js"></script>
<style>
#main {
margin: 0px;
padding: 0px;
font-size: small;
}
</style>
<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">
// Display UI depending on OAuth access state of the gadget (see <divs> above).
// If user hasn't approved access to data, provide a "Personalize this gadget" link
// that contains the oauthApprovalUrl returned from makeRequest.
//
// If the user has opened the popup window but hasn't yet approved access, display
// text prompting the user to confirm that s/he approved access to data. The user
// may not ever need to click this link, if the gadget is able to automatically
// detect when the user has approved access, but showing the link gives users
// an option to fetch their data even if the automatic detection fails.
//
// When the user confirms access, the fetchData() function is invoked again to
// obtain and display the user's data.
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";
}
}
}
// Process returned JSON feed to display data.
function showResults(result) {
showOneSection('main');
var titleElement = document.createElement('div');
var nameNode = document.createTextNode(result.feed.title.$t);
titleElement.appendChild(nameNode);
document.getElementById("main").appendChild(titleElement);
document.getElementById("main").appendChild(document.createElement("br"));
list = result.feed.entry;
for(var i = 0; i < list.length; i++) {
entry = list[i];
var divElement = document.createElement('div');
divElement.setAttribute('class', 'name');
var valueNode = document.createTextNode(entry.gd$email[0].address);
divElement.appendChild(nameNode);
divElement.appendChild(valueNode);
document.getElementById("main").appendChild(divElement);
}
}
// Invoke makeRequest() to fetch data from the service provider endpoint.
// Depending on the results of makeRequest, decide which version of the UI
// to ask showOneSection() to display. If user has approved access to his
// or her data, display data.
// If the user hasn't approved access yet, response.oauthApprovalUrl contains a
// URL that includes a Google-supplied request token. This is presented in the
// gadget as a link that the user clicks to begin the approval process.
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);
}
// Call fetchData() when gadget loads.
gadgets.util.registerOnLoadHandler(fetchData);
</script>
]]>
</Content>
</Module>
注: ガジェットに行 <Require feature="locked-domain"/> を追加して、locked-domain 機能を選択することをおすすめします。さらに、popup.js の独自のコピーをホストすることをおすすめします。
まずガジェットの <ModulePrefs> セクション内に <OAuth> セクションを追加する必要があります。
<?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 サービス構成を指定します。次の表をご覧ください。
| 要素 | 説明 |
|---|---|
/ModulePrefs/OAuth/Service |
この要素は単独の OAuth サービス構成です。 属性:
|
/ModulePrefs/OAuth/Service/Request |
これらの要素は、OAuth リクエスト トークンの URL とアクセス トークンの URL を表します。詳しくは、OAuth 仕様とウェブ アプリケーション用の OAuth 認証をご覧ください。 属性:
|
/ModulePrefs/OAuth/Service/Authorization |
OAuth 認証 URL。ガジェットがユーザー データにアクセスするのにそのユーザーの承認を求める必要がある場合、この URL に対してポップアップ ウィンドウが開きます。 |
認証 URL には oauth_callback クエリ パラメータが含まれます。ユーザーがそのユーザーのデータへのアクセスを承認すると、OAuth サービス プロバイダはこの URL にリダイレクトされます。http://oauth.gmodules.com/gadgets/oauthcallback を oauth_callback URL として指定する必要があります。oauthcallback ページには、ポップアップ ウィンドウを自動で閉じる JavaScript のスニペットが含まれます。ガジェットはポップアップ ウィンドウが閉じられたことを検出して、ユーザー データのフェッチを試みることができます。
OAuth ガジェットは承認されたユーザーのデータをフェッチします。これを行うには、ユーザーは、サービス (この例では Google Data Contacts) がユーザー データをガジェットと共有できるよう許可を与える必要があります。
たとえば連絡先のサンプル ガジェットを考えます。イベントの順に説明します。
gadgets.util.registerOnLoadHandler(fetchData) が呼び出され、これによりfetchData() 関数が呼び出されます。fetchData() 関数は makeRequest() を呼び出します。 makeRequest() 関数はコールバック パラメータを指定します。コールバック パラメータに渡される JavaScript オブジェクトには、makeRequest() が返す通常の値の他に、OAuth 専用のフィールドがあります。 fetchData() 関数を次に示します。
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);
}
ガジェットがコールバックを処理するときに最初にチェックするのは、response.oauthApprovalUrl に null 以外の値が含まれているかどうかです。ユーザーがそのユーザー データへのアクセスを許可していない場合、response.oauthApprovalUrl に URL が含まれます。ユーザーはこの URL にアクセスして、ガジェットがデータにアクセスすることを許可する必要があります。この URL には、サービス プロバイダ (この場合は Google) が発行したリクエスト トークンが含まれます。
ガジェットは、ポップアップ ウィンドウを管理するための shindig.oauth.popup オブジェクトを最初に作成します。shindig.oauth.popup にはいくつかのパラメータがあります。
var popup = shindig.oauth.popup({
destination: response.oauthApprovalUrl,
windowOptions: null,
onOpen: function() { showOneSection('waiting'); },
onClose: function() { fetchData(); }
});
destination パラメータには、ポップアップ ウィンドウを開く URL を指定します。
windowOptions パラメータには、ブラウザ提供の window.open 関数に渡すオプションを指定します。ポップアップ ウィンドウで使用されるサイズ、配置、クロムを制御できます。ブラウザが異なればサポートされる window.open へのパラメータも異なります。詳しくは、Internet Explorer と Firefox のマニュアルを参照してください。
ユーザーがリンクをクリックしてポップアップを開くときに、onOpen 関数が呼び出されます。このガジェットは showOneSection('waiting') を呼び出して適切なメッセージを表示し、ユーザーがアクセスを承認するまで待機します。
ポップアップ ウィンドウを閉じるときに、onClose 関数が呼び出されます。ポップアップ ウィンドウが閉じられると、ガジェットはユーザー データを取得するための fetchData() の呼び出しを登録します。
ポップアップ オブジェクトを作成したら、onclick ハンドラを DOM 要素に関連付けてウィンドウの開始を制御する必要があります。このガジェットでは、approval <div> 内にある personalize HREF の onclick ハンドラを、ポップアップ ウィンドウを開くように設定しています。
var personalize = document.getElementById('personalize');
personalize.onclick = popup.createOpenerOnClick();
またこのガジェットでは、waiting <div> 内にある approvaldone HREF を popup.createApprovedOnClick() ハンドラに設定しています。approvaldone HREF がクリックされると、ガジェットはポップアップ ウィンドウを閉じてユーザー データのフェッチを試みます。ユーザーが [I've approved] リンクをクリックしなくても済むことが望ましいのですが、クリックされたときの場合に備えて onclick ハンドラを付加する必要があります。
var approvaldone = document.getElementById('approvaldone');
approvaldone.onclick = popup.createApprovedOnClick();
ガジェットは approval <div> を表示して、ユーザーにリンクをクリックしてポップアップを開くよう求めます。不必要なポップアップ ウィンドウが開かれないように、多くのブラウザではポップアップ ブロッカーが使用されています。このポップアップ ブロッカーによってブロックされないように、ガジェットでは、ユーザーがボタンまたはリンクをクリックするまで、ポップアップ ウィンドウが開かれないようにする必要があります。
showOneSection('approval');
ガジェットは <div> と showOneSection() 関数を使い、ガジェットの承認状態に基づいて適切な UI を表示します。考えられるガジェットの状態ごとに 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> はエラーの表示にも使用されます。 <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";
}
}
}
makeRequest() 関数の詳細については、リモート コンテンツのフェッチをご覧ください。この関数は、リモートのウェブ コンテンツを取得したり操作したりするのに使用します。この関数には、次の引数を指定します
String url - コンテンツがある URL です。Function callback - URL からデータをフェッチした後、そのデータを使用して呼び出す関数です。Map.<gadgets.io.RequestParameters, Object> opt_params - 要求に渡す追加パラメータです。 opt_params[gadgets.io.RequestParameters.AUTHORIZATION] が gadgets.io.AuthorizationType.OAUTH に設定されている場合、コンテナは OAuth を使用して、要求に指定されたリソースへのアクセス権を取得する必要があります。通常この場合、サービス プロバイダにアクセス権を与えるようにユーザーに指示することで、ガジェットがユーザーのコンテンツを取得することが必要になります。
次の追加の OAuth パラメータは opt_params に指定できます。
| パラメータ | 説明 |
|---|---|
gadgets.io.RequestParameters.OAUTH_SERVICE_NAME |
ガジェットが XML 仕様の OAuth <Service> 要素を参照するのに使用するニックネームです。サービス名は <ModulePrefs> の下の /ModulePrefs/OAuth/Service XML セクションに指定することもできます。どちらの場所にも指定しない場合は "" がデフォルト値になります。 |
gadgets.io.RequestParameters.OAUTH_TOKEN_NAME |
特定のリソースへのアクセス権を与える OAuth トークンを、ガジェットが参照するのに使用するニックネームです。指定しない場合は "" がデフォルト値になります。同じサービス プロバイダから複数のリソースにアクセスする場合、ガジェットは複数のトークン名を使用できます。たとえば連絡先リストとカレンダーにアクセスするガジェットの場合、連絡先リストのトークンには「contacts」というトークン名を使用し、カレンダーのトークンには「calendar」という連絡先リストを使用できます。 |
gadgets.io.RequestParameters.OAUTH_REQUEST_TOKEN |
サービス プロバイダによっては、リソースへのアクセスが事前承認済みのリクエスト トークンをガジェットに自動的に供給できます。ガジェットはそのトークンを、 パラメータと共に使用できます。このパラメータはオプションです。 |
gadgets.io.RequestParameters.OAUTH_REQUEST_TOKEN_SECRET |
あらかじめ承認されたリクエスト トークンに対応するシークレットです。このパラメータはオプションです。 |
gadgets.io.RequestParameters.OAUTH_USE_TOKEN |
このパラメータに指定できる値は、「never」、「if_available」、「always」のいずれかです。サービス プロバイダの API によっては、OAuth アクセス トークンを必要としないものがあります。このような API は OAuth コンシューマ キーを使って呼び出し元アプリケーションを認証して、要求を続行できるようにします。このような API にアクセスするためのユーザーの承認を不必要に求めないようにするには、 一部の OAuth API は、ユーザーが承認を与えていない場合、限定されたデータを提供しますが、ユーザーが呼び出し元アプリケーションにアクセス トークンを与えている場合は追加機能を提供することができます。OAuth アクセス トークンを受け付けることができる API を使用していても、そのトークンが必要でない場合は、 多くの OAuth API はアクセス トークンが送信された場合にのみ機能します。このような API は、使用する前にユーザーの承認を求める必要があります。使用可能なアクセス トークンがあることを必須とするには、
|
OAuth を使用する場合、コンテナはガジェットに代わって OAuth プロトコルを実行します。OAuth サービス プロバイダについてで説明したとおり、ガジェットが iGoogle で使用するコンシューマ キーを登録していない場合、iGoogle はそのデフォルトの RSA 署名キーを使用します。
makeRequest() のコールバック パラメータに渡される javascript オブジェクトには、makeRequest() が返す通常の値の他に、次の OAuth 専用のフィールドがあります。
| OAuth フィールド | 説明 |
|---|---|
oauthApprovalUrl |
この値が指定されている場合、その値はサービス プロバイダが発行したリクエスト トークンを含む URL です。これが null 値以外の場合、ユーザーは外部のページに移動し、データにアクセスしようとするガジェットの要求を承認する必要があります。ポップアップ ウィンドウを使用して、ユーザーを外部のページに移動させることを推奨します。アクセスが承認されると、ガジェットは makeRequest() を何度でも呼び出してデータを取得できます。 |
oauthError |
この値が指定されている場合、OAuth 関連のエラーが発生したことを示します。 |
oauthErrorText |
この値が指定されている場合、OAuth 関連のエラーが発生したことを示します。ガジェットのデベロッパーはこの値をデバッグ情報として使用できます。パラメータ:
|
OpenSocial コンテナは、追加の署名付きパラメータを OAuth 要求に渡すことで、要求のコンテキストに関する追加情報を OAuth サービス プロバイダのサイトに提供できます。opensocial_owner_id や opensocial_app_url などの追加パラメータについて詳しくは、gadgets.io.makeRequest のドキュメントをご覧ください。OpenSocial に対応するサービス プロバイダであれば、これらのパラメータを使って追加データをユーザーに返すことができます。たとえばサービス プロバイダは、ガジェットの閲覧者に関する情報だけでなく、閲覧者の友だちに関する情報も返すことができます。
上の例では、データをフェッチするのに gadgets.* makeRequest() メソッドが使用されます。しかし、Google Data API を使用すると、OAuth プロキシで動作する Google Data の JavaScript ライブラリを利用できます。これはバックグラウンドで makeRequest() を呼び出すので、ガジェットの最終的な結果は同じになります。
詳細と例については、記事 Creating a Google Data Gadget をご覧ください。
OAuth サービス プロバイダであれば、承認用のポップアップ ウィンドウを表示しないようにすることでガジェットのユーザー エクスペリエンスを向上できます。ユーザーがサービス プロバイダのサイトからガジェットを追加する場合、ユーザー データのアクセス権の取得に使用される事前承認済みの OAuth リクエスト トークンを iGoogle に渡すことができます。
フローは次のとおりです。
addmodule URL へのリダイレクト URL をユーザーに送信します。リダイレクト URL には、リクエスト トークンとリクエスト トークン シークレット (オプション) が含まれます。OAuth の事前承認 URL は、事前承認済みの OAuth リクエスト トークンを作成して、そのトークンを使用するようにユーザーを addmodule URL にリダイレクトする必要があります。事前承認済みの OAuth トークンの作成方法は OAuth サービス プロバイダの詳細によって異なりますが、事前承認済みのトークンには次の特性が必要です。
事前承認済みのリクエスト トークンの作成が完了したら、サービス プロバイダ サイトは、その事前承認済みのリクエスト トークン (およびオプションでトークン シークレット) を要求内に含めて、iGoogle addmodule へのリダイレクト URL をユーザーに送信する必要があります。リダイレクトは次のような URL です。
http://www.google.com/ig/add?moduleurl=<URL OF GADGET>&up_request_token=<REQUEST TOKEN>&up_request_token_secret=<REQUEST TOKEN SECRET>
どのリダイレクト URL もそうですが、クエリ パラメータは URL エンコードされている必要があります。
up_ の接頭辞で始まるパラメータは、ガジェットのユーザー設定として処理されます。up_rt パラメータの値は、ガジェット内の rt ユーザー設定の値になります。iGoogle では、これらのユーザー設定に使用できる文字は、英数字、ピリオド (.)、スペースに限定されます。リクエスト トークンまたはリクエスト トークン シークレットに他の文字が含まれる場合、それらの文字をガジェットに自動で追加することを iGoogle が許可する前に、それらの文字のエンコードが必要になる場合があります。
事前承認済みのリクエスト トークンを使用するには、ガジェットを少し変更する必要があります。まず、setprefs 機能を要求するようにガジェット仕様を更新します。次に、リクエスト トークンとリクエスト トークン シークレット用の 2 つの新しいユーザー設定を宣言するようにガジェット仕様を更新します。
...
<ModulePrefs title="Preapproved OAuth Gadget" scrolling="true">
<Require feature="setprefs" />
<OAuth>
<Service>
...
</Service>
</OAuth>
</ModulePrefs>
<UserPref name="request_token" required="false" datatype="hidden"></UserPref>
<UserPref name="request_token_secret" required="false" datatype="hidden"></UserPref>
...
ガジェット仕様にこれらのパラメータを追加したら、ガジェット スクリプトが新しいユーザー設定を gadgets.io.makeRequest() 関数に渡すようにする必要があります。例を次に示します。
params.AUTHORIZATION = "OAUTH";
var prefs = new gadgets.Prefs();
var requestToken = prefs.getString("request_token");
if (requestToken !== "") {
// We have a preapproved request token
params.OAUTH_REQUEST_TOKEN = requestToken;
params.OAUTH_REQUEST_TOKEN_SECRET = prefs.getString("request_token_secret");
// Preapproved request tokens are only good once
prefs.set("request_token", "");
prefs.set("request_token_secret", "");
}
gadgets.io.makeRequest(url, callback, params);
まず、request_token ユーザー設定を使用する必要があるかどうかをチェックします。
var prefs = new gadgets.Prefs();
var requestToken = prefs.getString("request_token");
if (requestToken !== "") {
...
}
request_token ユーザー設定が空でない場合、ガジェットは値 params.OAUTH_REQUEST_TOKEN と params.OAUTH_REQUEST_TOKEN_SECRET を設定して、事前承認済みのリクエスト トークンの使用を試みます。
if (requestToken !== "") {
// We have a preapproved request token
params.OAUTH_REQUEST_TOKEN = requestToken;
params.OAUTH_REQUEST_TOKEN_SECRET = prefs.getString("request_token_secret");
// Preapproved request tokens are only good once
prefs.set("request_token", "");
prefs.set("request_token_secret", "");
}
事前承認済みのリクエスト トークンを使用できるのは 1 回のみです。ガジェットが同じユーザー設定を再使用できないようにするには、ユーザー設定が makeRequest() パラメータにコピーされた後に prefs.set() を呼び出してユーザー設定をクリアする必要があります。
prefs.set("request_token", "");
prefs.set("request_token_secret", "");
最後に、更新されたパラメータを使って gadgets.io.makeRequest() を呼び出します。事前承認済みのリクエスト トークンが有効な場合、ガジェットはユーザー データにアクセスでき、ユーザーの承認を得るためのポップアップ ウィンドウが開くことを回避できます。
ガジェットがこれらの事前承認済みのリクエスト トークンを使ってデータにアクセスできるよう求める場合でも、ポップアップ ウィンドウを使ってユーザーが許可を与えることができるようにする必要があります。ユーザーがあなたのガジェットを iGoogle ディレクトリから追加する場会、事前承認済みのリクエスト トークンはありません。
OAuth ガジェットの作成に役立つその他のサンプル OAuth ガジェットをいくつか紹介します。
Google はこの機能を強化する多くの拡張機能に取り組んでいます。これらの拡張機能や、OAuth で使用できるその他の高度な技法についてお知りになりたい方は、Google が提供する OAuth の高度な技法に関するサイトをご覧ください。