読者です 読者をやめる 読者になる 読者になる

Titanium MobileでTwitterのOAuth認証でプロフィール画象アイコンの変更する

TwitterのOAuth認証はAuthorizationヘッダ方式がおすすめらしいとのこと。
http://dev.twitter.com/pages/auth


とりあえず今回はTitanium Mobileで開発を行っているためappceleratorブログで紹介されていたOAuthライブラリを利用してみることに。


しかしながら、このoauth-adapterライブラリは二つ問題があります。

  • OAuth認証が(postbody内での)パラメータ渡しになっている
  • OAuthAdapter.sendメソッドに渡したAPIパラメータが全てoauth_signature生成時の署名対象になってしまう。


前者に関してはそもそもTwitterのOAuth認証はAuthorizationヘッダ方式が推奨されていることからあまり芳しくはないけど、まぁほとんどのAPIではパラメータ渡しでも動くのですぐには問題にならない。
※ちなみにjavaのTwitterAPIライブラリであるTwitter4Jはソース見たらちゃんとAuthorizationヘッダでPOSTしていました。


しかし、update_profile_imageやupdate_profile_background_imageのプロフィール画象変更するAPIに関しては、この二つの問題から動作しないのです。


update_profile_imageやupdate_profile_background_imageは「OAuth による本API実行時の oauth_signature 生成に際しては “image 引数”は署名の対象には含まない」とのことなので、oauth_adapter.jsのsendメソッドで普通にパラメータで渡してしまうと署名対象に入ってしまってOAuth認証を通すことができません。


なので、twitterのプロフィール画象を変更するupdate_profile_imageやupdate_profile_background_imageなどのmultipartでPOSTするようなAPIは対応できません。
※OAuthの場合、multipartで送るときはAuthorizationヘッダ方式で送ってやらないとだめみたいです。


oauth-adapterのOAuth認証まわりをAuthorizationヘッダ方式に全部書き直したいところだけどそこまでやるのは面倒なので、、、
とりあえずoauth_adapter.jsのsendメソッドの下あたりにAuthorizationヘッダ方式+multipartでファイル送信するメソッドを追加してみました。

    var sendMultiPart = function(pUrl, realm, pParameters, pTitle, pSuccessMessage, pErrorMessage)
    {
        Ti.API.debug('Sending a message to the service at [' + pUrl + '] with the following params: ' + JSON.stringify(pParameters));

        if (accessToken == null || accessTokenSecret == null)
        {

            Ti.API.debug('The send status cannot be processed as the client doesn\'t have an access token. The status update will be sent as soon as the client has an access token.');

            actionsQueue.push({
                url: pUrl,
                parameters: pParameters,
                title: pTitle,
                successMessage: pSuccessMessage,
                errorMessage: pErrorMessage
            });
            return;
        }

        accessor.tokenSecret = accessTokenSecret;

        var message = createMessage(pUrl);
        message.parameters.push(['oauth_token', accessToken]);
        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message, accessor);

        parameterMap = {};
        for(p in pParameters) {
                parameterMap[pParameters[0][0]] = pParameters[0][1];
        }
		
        var client = Ti.Network.createHTTPClient();
        client.open('POST', pUrl, false);
        client.setRequestHeader("Authorization", OAuth.getAuthorizationHeader(realm, message.parameters) );
        client.send(parameterMap);

        if (client.status == 200) {
            Ti.UI.createAlertDialog({
                title: pTitle,
                message: pSuccessMessage
            }).show();
        } else {
            Ti.UI.createAlertDialog({
                title: pTitle,
                message: pErrorMessage
            }).show();
        }

        Ti.API.debug('*** sendStatus, Response: [' + client.status + '] ' + client.responseText);

        return client.responseText;

    };
    this.sendMultiPart = sendMultiPart;


呼び出し方はAPI呼び出しの部分を

        var file = Ti.Filesystem.getFile("hoge_image.jpg");
	oAuthAdapter.sendMultiPart('http://api.twitter.com/1/account/update_profile_image.json', //←sendメソッドではなくsendMultiPartに変更
						"hogehoge",  //←Authorizationヘッダで指定するrealmを入れる
						[['image', file.read()]], 
						'Twitter', 
						'Published.', 
						'Not published.');

な感じで書いてあげればちゃんと画象変更できるようになりました。


ここらへんが超参考になった
The OAuth 1.0 Protocol
Twitter API 仕様書 日本語訳 第五十版
OAuth(Twitter API)
JavaScript で OAuth 認証を行う方法