Search code examples
javascriptnode.jsoauthwithings

Withings API is not working with node-oauth


I'm attempting to authenticate requests to the Withings API using node-oauth, a widely used OAuth module for Node. All of the initials steps of the OAuth process are working, and I'm able to acquire the user ID, access token, and access token secret. However, when attempting to actually use these tokens to make an authenticated request, I get one of the following errors:

  • 2554 Wrong action or wrong webservice
  • 2555 An unknown error occurred
  • 2556 Service is not defined

I've verified that the credentials I'm using are valid by testing them here. Am I doing something wrong, or is the Withings API implemented in some non-standard way, which makes it incompatible with node-oauth?

var consumerKey = "";
var consumerSecret = "";
var oauth_access_token = "";
var oauth_access_token_secret = "";
var userid = "";

var oauth = require("oauth");

var withings = new oauth.OAuth(
    "https://oauth.withings.com/account/request_token",
    "https://oauth.withings.com/account/access_token",
    consumerKey,
    consumerSecret,
    "1.0",
    null,
    "HMAC-SHA1"
);

var url = "http://wbsapi.withings.net/measure?action=getmeas&userid=" + userid;
withings.get(url, oauth_access_token, oauth_access_token_secret, function(error, response) {
    console.log(response);
});

Output:

{"status":2554}

Solution

  • I figured this one out. The node-oauth library assumes that most APIs expect OAuth parameters to be defined in headers. However, OAuth parameters may also be defined in the query string, which is how Withings decided to implement it. The node-oauth library defines a signUrl function for this purpose, but you must use it explicitly. Once you wrap the URL in that function, the problem is solved. Note that there is no need to pass the access tokens into the get function because the request is already signed.

    var url = withings.signUrl("http://wbsapi.withings.net/measure?action=getmeas&userid=" + userid, oauth_access_token, oauth_access_token_secret);
    withings.get(url, null, null, function(error, response) {
        console.log(response);
    });