OAuth1.0 Using NodeJS and Axios - 401 Error (Authorization Header)

52 Views Asked by At

I've been using Postman to making an object that I need to include in a axios request that uses OAuth1.0, Postman does it successfully. Now I'm attempting to do it without Postman so that I can automate things but I'm having trouble using OAuth1.0. I am using the npm package oauth1.0a and have installed my necessary dependencies like crypto. I am successfully putting the Authorization header in the right place for the request, but when I log it, it looks different from Postman, and the parameters are in a different order. The documentation that I have read for Oauth1.0a seems to indicate that order matters, so I am not sure why mine is coming out of order. This is what the authorization header is supposed to look like:

'Authorization': 'OAuth oauth_consumer_key="XXX",oauth_token="XXX",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1559312415",oauth_nonce="XXX",oauth_version="1.0",oauth_signature="XXX"'

and this is what mine is coming out as (note the difference in order):

Authorization: 'OAuth oauth_consumer_key="XXXXXX",oauth_nonce="XXXXX",oauth_signature="XXXXXX",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1709321223",oauth_token="XXXXX",oauth_version="1.0"'

Does the order matter? If so, how do I correct it? Is there anything else wrong with what I am doing?

I have referenced this post for help: OAuth1.0 header in Node.js

I have tried to manipulate the authorization header string and put things in order. I have double and triple checked my consumer keys and tokens, and they are correct because Postman is using those and those requests are successful. I have tried to make my code match Postman as much as possible. I have changed parameters in my OAuth instance (', ' vs '' between params), as well as the length of the nonce (Postmans oauth_nonce is 11 characters). Have also referenced the Twitter API documentation here: https://developer.twitter.com/en/docs/authentication/oauth-1-0a/authorizing-a-request. Have also asked ChatGPT for it's understanding of the problem.

Here's the relevant code with some portions abstracted away:

let data = JSON.stringify({
"text": "Hello World!"
}); 
const OAuth = require('oauth-1.0a'); 
const crypto = require('node:crypto'); 
// const crypto = import('node:crypto');
const oauth = OAuth({ 
  consumer: {
      key: '<key>',
      secret: '<secret>'
  }, 
  signature_method: 'HMAC-SHA1',
  hash_function(base_string, key) {
      return crypto.createHmac('sha1', key).update(base_string).digest('base64');
  }, 
  // nonce_length: 11, 
  parameter_seperator: ','
});
const token = {
  key: '<tokenkey>',
  secret: '<tokensecret>'
}
let request = {
  url: 'https://api.twitter.com/2/tweets', 
  method: 'POST',
  data: data
}
let authorization = oauth.authorize(request, token); 
let headers = oauth.toHeader(authorization); 

let config = {
  method: 'post',
  maxBodyLength: Infinity,
  url: 'https://api.twitter.com/2/tweets',
  headers: { 
    'Content-Type': 'application/json', 
    'Authorization': `${headers.Authorization}`,  
    'Cookie': 'guest_id=xxx; guest_id_ads=xxx; guest_id_marketing=xxx; personalization_id="xxx"'
  },
  data : data
};

    axios.request(config)
    .then((response) => {
      console.log(JSON.stringify(response.data));
    })
    .catch((error) => {
      console.log(error.message);
    });
1

There are 1 best solutions below

0
tjohnson009 On

I missed an error in the request object. Instead of having a "body" attribute, I erroneously put a "data" attribute. This body attribute is required for the request object to be used properly by the OAuth instance. As for if the order matters, I have seen some say it does, and others say it doesn't. I implemented a function that changed the order of the authorization string, so I still don't know definitively in this instance. I am leaning toward the option that it does not matter. Press on.