FeedHive/twitter-api-client

Access token and secret required for pre-access token OAuth 1.0 steps

alecejones opened this issue · 4 comments

Hi there,

I'm attempting to implement the standard 3-leg sign-in process using OAuth 1. After I input the consumer api key and consumer secret, the next step is to request an OAuth token which I can later exchange for an access token.

However, browsing the source code of this project, I noticed that the class constructor automatically throws an error if the access token and access token secret are not provided. This makes sense, but the code should not throw an error for values that should not exist yet. Actually, the typescript interface permits the access token and secret properties to be omitted, but the source code itself throws an error if they are.

I also tried to just enter placeholder values so the error would not occur at instantiation. But these were not accepted by Twitter:

{
statusCode: 401,
data: '{"errors":[{"code":89,"message":"Invalid or expired token."}]}'
}

I assume the client is embedding the placeholder with the request, which also makes sense but is unhelpful in this context. The whole situation is kind of a catch-22.

Hi 😊

This is actually not a bug.
This is what the Twitter API expects. When obtaining the access tokens, you need to initially use the ones you create from your developer portal.

See the explanation here:
#61 (comment)

Are you sure about this? I understand that it would make sense, since the request has to be signed (and that ostensibly requires oauth token + secret). However, Twitter API documents explicitly state that there are some flows where this is not the case, and so the signature method is slightly different. See the below quote.

If you scroll to the section "Getting a signing key":

https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature

"Note that there are some flows, such as when obtaining a request token, where the token secret is not yet known. In this case, the signing key should consist of the percent encoded consumer secret followed by an ampersand character ‘&’."

I still have to take the time to test this out on my own and see if it can be done. I've read through the docs several times and admittedly they are unclear in some parts.

Cool, thanks a lot.
I'm gonna close this issue now, but please, you are very welcome to still report your findings back on this.
That would be greatly appreciated 🙏

So, upon investigation, I have confirmed my initial suspicion that the POST /oauth/request_token endpoint does NOT require a token and secret. I was able to successfully fetch a token and secret basically like this:

`

const consumer = new oauth.OAuth(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"CONSUMER_KEY",
"CONSUMER_SECRET",
"1.0",
"MY_CALLBACK_URL",
"HMAC-SHA1"
);

const promise = new Promise((resolve, reject) => {
  consumer.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results){
    if (error) {
      reject(error)
    } else {  
      resolve({
        ...results,
        oauth_token,
        oauth_token_secret,
      })
    }
  });
})

`

I found this method and was able to successfully use it from the Github Gist here:
https://gist.github.com/joshj/1933640

So yes, per my initial recommendations, the Twitter Client class should permit instantiation without those tokens being provided beforehand, and allow them to be set using the request token flow.