Search code examples
twitterfirefox-addon

How to authenticate with twitter from a firefox plugin


Echofon abandoned their firefox twitter plugin around April 2013, but it's been maintained on github until some recent changes to the twitter API broke it.

In normal use, authentication should follow PIN-based authentication, but instead the request to https://api.twitter.com/oauth/request_token is returning "{"errors":[{"code":32,"message":"Could not authenticate you."}]}'" status='401'

I think the problem is in the TwitterClient.buildOAuthHeader function

TwitterClient.buildOAuthHeader = function (user, method, url, param)
{
  var ts = Math.ceil(Date.now() / 1000);
  var diff = EchofonUtils.timestampDiff();
  if (diff != 0) {
    EchofonUtils.debug("local timestamp " + ts + " / server timetsamp " + (ts + diff));
    ts += diff;
  }

  var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
  converter.charset = "UTF-8";
  var result = {};
  var data = converter.convertToByteArray(user + Date.now() + url + Math.random(), result);
  var ch = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
  ch.init(ch.MD5);
  ch.update(data, data.length);
  var hash = ch.finish(false);

  var s = convertToHexString(hash);

  var oauthparam = {"oauth_consumer_key"     : OAUTH_CONSUMER_KEY,
            "oauth_timestamp"        : ts,
            "oauth_signature_method" : "HMAC-SHA1",
            "oauth_nonce"            : s + Math.random(),
            "oauth_version"          : "1.0"};

  if (user.oauth_token) {
    oauthparam["oauth_token"] = EchofonAccountManager.instance().get(user.user_id).oauth_token;
  }

  var dict = {};
  for (var key in param) dict[key] = param[key];
  for (var key in oauthparam) dict[key] = oauthparam[key];

  var paramStr = encodeURLParameter(dict);

  var base = [method, RFCEncoding(url), RFCEncoding(paramStr)].join("&");

  var signature;
  var secret = user.oauth_token_secret ? EchofonAccountManager.instance().get(user.user_id).oauth_token_secret : "";
  var signature = EchofonSign.OAuthSignature(base, secret);

  oauthparam['oauth_signature'] = signature;

  var headers = [];
  for (var key in oauthparam) {
    headers.push(key + '="' + RFCEncoding(oauthparam[key]) + '"');
  }
  headers.sort();

  return headers.join(",");
}

I've registered a new application at dev.twitter.com and I'm using the consumer key from that instead of the one in the repository.

Also, I've added the oauth_callback attribute to the oauthparam object, with the value set to "oob" as detailed in the PIN-based authentication link above, but the plugin is not authenticating correctly with the API.

What needs to be changed in the authorization header to correct this?


Solution

  • This issue has been resolved. Instructions on how to install a patched version of the plugin here - https://github.com/echofox-team/echofon-firefox-unofficial/issues/85#issuecomment-581843812