ciaranj / node-oauth

OAuth wrapper for node.js
MIT License
2.44k stars 662 forks source link

Receiving error: "status":342 #347

Open SSTPIERRE2 opened 6 years ago

SSTPIERRE2 commented 6 years ago

Hi all, I've been running some code that gets measurement data via Nokia API for months now, but sometime in mid-February it started hitting this error: {"status":342,"body":{},"error":"The signature (using Oauth) is invalid"} for every user I try to get data for.

Here's the gist of the code. The function below is used in a loop of user tokens/secrets to get their data.

function processUser(user, option) {
    var oauth = require("oauth");
        var withings = new oauth.OAuth(
            "https://developer.health.nokia.com/account/request_token",
            "https://developer.health.nokia.com/account/access_token",
            user.ckey,
            user.csecret,
            "1.0",
            null,
            "HMAC-SHA1"
        );
        var url = withings.signUrl(`
                  http://api.health.nokia.com/v2/measure?action=getactivity&startdateymd=2017-06-15&enddateymd=${today}&userid=${user.Userid}`, 
                  user.otoken, 
                  user.osecret
                );
        withings.get(url, null, null, function(error, response) {
                  ...Do things with the response
                }
}

Did something change in Nokia's API that I need to change this code for? If others aren't seeing this error then maybe I can change something to get it working again.

floetenbaer commented 6 years ago

I think, the problem is in OAuth.prototype._prepareParameters in oauth.js

After calling signUrl (which uses _prepareParameters) the parameter 'oauth_signature' is already in the extra_params. So when calling get (which calls _prepareParameters again) the signature is calculated inclusive the first 'oauth_signature' and it appends another new parameter 'oauth_signature which ist incorrect. Excluding the 'oauth_signature' in prepareParameters helps for me. See the new two lines:

   if( parsedUrl.query ) {
      var key2;
      var extraParameters= querystring.parse(parsedUrl.query);
      for(var key in extraParameters ) {
        /* NEW */ if (key !== 'oauth_signature') { /* dont calculate signature with oauth_signature */**
          var value= extraParameters[key];
          if( typeof value == "object" ){
            // TODO: This probably should be recursive
            for(key2 in value){
              oauthParameters[key + "[" + key2 + "]"] = value[key2];
            }
          } else {
            oauthParameters[key]= value;
          }
        /* NEW */  }
      }
    }
SSTPIERRE2 commented 6 years ago

Thank you for the reply!

Update: I found that the url produced by

var url = withings.signUrl(`
                  http://api.health.nokia.com/v2/measure?action=getactivity&startdateymd=2017-06-15&enddateymd=${today}&userid=${user.Userid}`, 
                  user.otoken, 
                  user.osecret
);

works by itself, so I instead used the request package to get from that URL and it works just fine.

Per the docs it seems like the signUrl part is unnecessary and I should be able to do something like

var url = http://api.health.nokia.com/v2/measure?action=getactivity&startdateymd=2017-06-15&enddateymd=${today}&userid=${user.Userid};

withings.get(url, user.otoken, user.osecret, function(error, response) {
                  ...Do things with the response
}

But I tried that and it didn't work. To me this signals that something may be wrong with this package's .get() method.