So I am trying to make authenticated calls to the API, but am getting error code 32: “Could not authenticate you.” I’ve read through the forums here and it seems the most common problem is percent encoding and parameter ordering. I also know I should be using a library and I plan to next time, but I’m so close now and want to understand what is happening behind the scenes anyway. Here’s my Node JS code to call users/show:
I am using the nonce and query-string modules.
const user = 'twitterdev';
const state = nonce();
const timeStamp = Math.floor((new Date()).getTime() / 1000);
var params = {
screen_name: user,
oauth_consumer_key: APP_KEY,
oauth_nonce: state,
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: timeStamp,
oauth_version: '1.0'
}
var oauthSignature = createSignature('GET', SHOW_URL, params);
var headerString = 'OAuth ' + encodeURIComponent('oauth_consumer_key') + '="' + encodeURIComponent(APP_KEY) + '", ' + encodeURIComponent('oauth_nonce') + '="' + encodeURIComponent(state) + '", ' + encodeURIComponent('oauth_signature') + '="' + encodeURIComponent(oauthSignature) + '", ' + encodeURIComponent('oauth_signature_method') + '="' + encodeURIComponent('HMAC-SHA1') + '", ' + encodeURIComponent('oauth_timestamp') + '="' + encodeURIComponent(timeStamp) + '", ' + encodeURIComponent('oauth_version') + '="' + encodeURIComponent('1.0') + '"';
var options = {
url: SHOW_URL,
headers: {
'authorization': headerString
},
qs: {
'screen_name': user,
},
json: true
};
request(options, function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log('User:', response.body);
} else if (response.statusCode == 404) {
console.log('User not found?');
if (body.errors) {
console.log(body.errors[0]);
}
} else {
if (error) {
console.log('Error: ', error);
}
console.log('Body error: ', body);
console.log('Status code: ' + response.statusCode);
//console.log(response.headers);
}
});
function createSignature(method, baseUrl, params) {
// sorts the keys and converts to query string, URI encoded (percent encoded)
const paramsString = querystring.stringify(params);
var signatureBaseString = method.toUpperCase() + '&' + encodeURIComponent(baseUrl) + '&' + encodeURIComponent(paramsString);
var signingKey = encodeURIComponent(APP_SECRET) + '&' + encodeURIComponent(APP_TOKEN_SECRET);
const generatedHash = crypto
.createHmac('sha256', signingKey)
.update(signatureBaseString)
.digest('base64');
return generatedHash;
}
When I print my data to the console at various stages (encoding parameters, signature, etc) it appears as though they are correctly encoded. You may also notice I do not have the oauth_token in my parameters, that’s because it is not required for this API call. Nonetheless I’ve tried including it too, and still get the same error.
Here’s what I see when I print out my request header:
{ authorization:
‘OAuth oauth_consumer_key=“HIDDEN”, oauth_nonce=“158222620297900”, oauth_signature=“3Q6%2FLYSDibRSD6nt80mNfDSZqmmo%2BwSetJ4hbjIeA3Y%3D”, oauth_signature_method=“HMAC-SHA1”, oauth_timestamp=“1582226202”, oauth_version=“1.0”’,
host: ‘CANT_SHOW_LINKS_IN_POST’,
accept: ‘application/json’ }
What am I missing? Am I hashing the secrets incorrectly? is encodeURIComponent not encoding correctly?