TwitterクライアントのOAuth対応(Javascript編)




6月にBasic認証が廃止されるということで、twitterクライアントのOAuth対応が必須となっています。twigadgeの方でもversion2.xとして対応しているわけですが、いろいろ資料を探してもJavascriptでの実装例をあまり見かけなかったので、メモとして残しておきます。
基本的な流れはTwitter API を OAuth で認証するスクリプトを 0 から書いてみたの通りなので、ここではコードの解説を主に書いていきます。

使用ライブラリ

Google CodeのOAuthライブラリ
# javascriptのものはSource->Browse以下に置いてあります。

JQuery
# ここで使っているのはAjax送信部分だけです。

認証手順

  1. Twitterでアプリケーション申請をして、Consumer Key/Consumer Secretを発行してもらう (ここでは省略)
  2. Request Token/Request Token Secretを取得する
  3. ユーザをTwitterに誘導してPINを取得してもらう
  4. Request Token/Request Token SecretとPINを元にAccess Token/Access Token Sceretを取得する
  5. Access Token/Access Token Secretを元にAPIにアクセスする

Request Token/Request Token Secretを取得する

まず、http://twitter.com/oauth/request_tokenにConsumer Keyを送ります。
他のパラメータとして、oauth_signature_methodはHMAC-SHA1、時刻とNonceはOAuth.setTimestampAndNonceで設定しています。パラメータを設定後、OAuth.SignatureMethod.signでConsumer Secretを使って署名を加えた後、OAuth.addToURLでURLにパラメータを付加し、そこにアクセスしています。パラメータのソートはライブラリがやってくれているので気にする必要はありません。どのAPIに対するアクセスも基本的には同じで、送るパラメータ、署名のkeyが変わるだけとなります。

  TwitterAPI.prototype.getRequestToken = function() {
    var accessor = {
      consumerSecret: this.consumer.consumerSecret,
      tokenSecret: ''
    };
   
    var message = {
      method: "GET",
      action: "http://twitter.com/oauth/request_token",
      parameters: {
        oauth_signature_method: "HMAC-SHA1",
        oauth_consumer_key: this.consumer.consumerKey
      }
    };
    OAuth.setTimestampAndNonce(message);
    OAuth.SignatureMethod.sign(message, accessor);
    var target = OAuth.addToURL(message.action, message.parameters);
    var options = {
      type: message.method,
      url: target,
      success: function(d, dt) { /* 返り値からRequest Token/Request Token Secretを取り出して、PINを取得するためのURLを作成 */ },
    };
    $.ajax(options); // 送信
  };

Access Token/Access Token Sceretを取得する

見て分かる通り、Request Token取得のコードとほとんど同じです。異なる点は以下になります

  • API”http://twitter.com/oauth/access_token”変更
  • 署名のkeyがConsumer Secret&Request Token Secretになる
  • パラメータoauth_tokenとしてRequest Tokenを送る
  • パラメータoauth_verifierとしてユーザが入力したPINを送る

取得したAccess Token / Access Token Secretをクライアントで保存しておけば、再度取得する必要はありません。

  TwitterAPI.prototype.getAccessToken = function(pin) {
    var accessor = {
      consumerSecret: this.consumer.consumerSecret,
      tokenSecret: this.token_secret // Request Token Secret
    };
   
    var message = {
      method: "GET",
      action: "http://twitter.com/oauth/access_token",
      parameters: {
        oauth_signature_method: "HMAC-SHA1",
        oauth_consumer_key: this.consumer.consumerKey,
        oauth_token: this.token, // Request Token
        oauth_verifier: pin
      }
    };
    OAuth.setTimestampAndNonce(message);
    OAuth.SignatureMethod.sign(message, accessor);
    var target = OAuth.addToURL(message.action, message.parameters);
    var options = {
      type: message.method,
      url: target,
      success: function(d, dt) { /* 返り値からAccess Token/Access Token Secretを取り出す */ },
    };
    $.ajax(options); // 送信
  };

GET/POSTを行う

Access Token / Access Token Secretを取得したら、それを使ってAPIにアクセスします。以下の点が変わります

  • 署名のkeyがConsumer Secret&Access Token Secretになる
  • パラメータoauth_tokenとしてAccess Tokenを送る
  • 送信データ全てを含めて署名をつける

下のコードがTweetを送信している部分になります。

  TwitterAPI.prototype.post = function(api, content, callback) {
    var accessor = {
      consumerSecret: this.consumer.consumerSecret,
      tokenSecret: this.atoken_secret // Access Token Secret
    };
   
    var message = {
      method: "POST",
      action: api,
      parameters: {
        oauth_signature_method: "HMAC-SHA1",
        oauth_consumer_key: this.consumer.consumerKey,
        oauth_token: this.atoken // Access Token
      }
    };
    // 送信するデータをパラメータに追加する
    for ( var key in content ) {
      message.parameters[key] = content[key];
    }
    OAuth.setTimestampAndNonce(message);
    OAuth.SignatureMethod.sign(message, accessor);
    var target = OAuth.addToURL(message.action, message.parameters);
    var options = {
      type: message.method,
      url: target,
      dataType: 'json',
      success: function(d, dt) { callback(d, dt); },
    };
    $.ajax(options); // 送信
  }
 
  // (中略)
 
    /**
     * update the status of user
     * @param[in] uptext - user status to update
     * @param[in] reply_to - target status id for reply
     */

    updateStatus: function(uptext, reply_to) {
      var content = {status: uptext, source: 'twigadge'};
      if(reply_to != '') {
        content.in_reply_to_status_id = reply_to;
      }
      twitterapi.post('http://twitter.com/statuses/update.json', content, Twigadge.dummy);
      System.Gadget.Flyout.show = false;
    },


TwitterクライアントのOAuth対応(Javascript編)” への11件のコメント

  1. ピンバック: TwitterクライアントのOAuth対応(Javascript編) | tomatomax.net | とっても! ちゅどん(雑記帳)

  2. ピンバック: twitterに異変。中国並みのネット検閲が始まった – もりやんの独断と偏見World (of the Moriyan, by the Moriyan, for the Moriyan) と19件… | twitterのこと、いろいろ。

  3. 勉強になりますっ!
    さっそく使ってみようと思いましたが、
    OAuth.SignatureMethod.sign(message, accessor);
    の所で「オブジェクトを指定してください」というエラーが出て止まってしましました。
    どうしてでしょう・・・・><

  4. はっきりとしたことは分かりませんが、エラーメッセージからするとoauthライブラリ(sha1ライブラリ)が読み込まれていないのではないでしょうか

  5. できました!ありがとうございます。
    よく読んだらsignature methodはsha1.jsの関数呼ぶって書いてありました。英語読めませんでした・・・・><

  6. 参考にさせていただこうと思ったのですが、TwitterAPI.protoypeのTwitterAPIが何者かわかりませんでした。
    以下のもので合っていますか?
    http://www.otchy.net/javascript/twitter-api/
    使用ライブラリ、という項があるのに記載がないのでちと不安でして。

  7. そっちでしたか。素早いお返事ありがとうございました

  8. ピンバック: OAuth for Greasemonkeyのラッパーライブラリ | Web scratch

  9. OAuth初心者なので非常に参考になりました。ただ初歩的な疑問なんですが、ajaxはクロスドメイン制限に引っかかって使用できないため、プロトコルのやり取りに使用できないのではないでしょうか?

  10. 「GET/POSTを行う」を参考につぶやきを投稿したいのですがうまくいきません。

    $.ajax(options);で送信後、エラーが帰ってきてしまいます。
    XMLHttpRequest情報をみても
    readyState 4 = complete
    status 0
    となってしまい、原因が不明です。JSのエラーは出ていません。

    http://twitter.com/statuses/update.jsonは
    http://api.twitter.com/1/statuses/update.json
    に変更してます。

    また、下記2点教えてください。
    OAuth.SignatureMethod.sign(message, accessor);

    ここではBASE64エンコードはされているのでしょうか。

    var target = OAuth.addToURL(message.action, message.parameters);

    targetをみるとパラメータの並びが自然ソートになっていないようなのですが、問題ないのでしょうか。oauth_signatureが最後にきていないなど。

    よろしくおねがいします。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です