Firefox OS 用に Twitter の OAuth 認証を実装したメモです。ポイントは、クロスオリジン XHR 通信 です。
方針
manifest.webapp の記述
クロスオリジン XHR 通信を行うためには、まず manifest.webapp の permissions に systemXHR を設定する必要があります。また、アプリケーションの type を privileged にする必要があります。manifest.webapp に以下の要領で項目を追加します。
"type": "privileged",
"permissions": {
"systemXHR": {
"description": "for OAuth"
}
}
description に入れる文字列は、任意で良いようです。アプリケーションの type を privileged(特権付き)にするということは、Mozilla の審査が必要となることを意味するため、いろいろ面倒ですね。アプリの権限設定については、MDN を参照してください。
XMLHttpRequest オブジェクト作成時の引数
OAuth 認証を行うための API 通信は、XMLHttpRequest オブジェクトを用いて行われることが多いでしょう。クロスオリジンな通信を行いたい場合、XMLHttpRequest オブジェクトをインスタンス化する際の引数に、{mozSystem: true}
というオブジェクトを渡してあげる必要があります。すなわち、
XHR = new global.XMLHttpRequest();
というコードだった場合、
XHR = new global.XMLHttpRequest({mozSystem: true});
のように書き換える必要があります。
実装
manifest.webapp に先述の記述を追加します。
次に、OAuth の実装です。今回は広く使われている jsOAuth ライブラリを用います。このライブラリでは、XMLHttpRequest オブジェクトの生成は隠蔽されていますから、ライブラリを少し改変したうえで、ビルドしなおす必要があります。
必要な変更は、1ファイル3行だけです。差分を以下に示します。
--- a/src/OAuth/Request.js
+++ b/src/OAuth/Request.js
@@ -10,18 +10,18 @@
} else if (typeof require !== 'undefined') {
// CommonJS require
try {
- XHR = new require("xhr").XMLHttpRequest();
+ XHR = new require("xhr").XMLHttpRequest({mozSystem: true});
} catch (e) {
// module didn't expose correct API or doesn't exists
if (typeof global.XMLHttpRequest !== "undefined") {
- XHR = new global.XMLHttpRequest();
+ XHR = new global.XMLHttpRequest({mozSystem: true});
} else {
throw "No valid request transport found.";
}
}
} else if (typeof global.XMLHttpRequest !== "undefined") {
// W3C
- XHR = new global.XMLHttpRequest();
+ XHR = new global.XMLHttpRequest({mozSystem: true});
} else {
throw "No valid request transport found.";
}
ビルドを行い、 js/jsOAuth.js
というファイル名で保存したとします。このファイルを使って、以下のように、 PIN コードベースの OAuth 認証を行うことができます。
参考:jsOAuth boilerplate for PIN based authentication in javascript
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jsOAuth.js"></script>
</head>
<body>
<script>
var config = {
consumerKey: "YOUCONSUMERKEY",
consumerSecret: "YOURCONSUMERSECRET",
requestTokenUrl: "https://api.twitter.com/oauth/request_token",
authorizationUrl: "https://api.twitter.com/oauth/authorize",
accessTokenUrl: "https://api.twitter.com/oauth/access_token"
};
var oauth = new OAuth(config);
oauth.fetchRequestToken(openAuthoriseWindow, failureHandler);
function openAuthoriseWindow(url)
{
var wnd = window.open(url, 'authorise');
setTimeout(waitForPin, 100);
function waitForPin()
{
if (wnd.closed)
{
var pin = prompt("Please enter your PIN", "");
oauth.setVerifier(pin);
oauth.fetchAccessToken(getSomeData, failureHandler);
}
else
{
setTimeout(waitForPin, 100);
}
}
}
function getSomeData()
{
oauth.get("https://api.twitter.com/1.1/statuses/home_timeline.json", function (data) {
}, failureHandler);
}
function failureHandler(data)
{
console.error(data);
}
</script>
</body>
</html>
以上です。Twitter 以外のウェブ API でも、同様に OAuth 認証が行えると思います。