desmondmorris / node-twitter

Client library for the Twitter REST and Streaming API's.
https://www.npmjs.com/package/twitter
MIT License
1.27k stars 237 forks source link

"Invalid or expired ", when using hellojs for oauth #324

Closed ajmas closed 5 years ago

ajmas commented 5 years ago

The OAuth2 authentication is being handled by a front-end, vue based application, using 'hellojs'. A sample response (real values modified) looks like:

authResponse: {
  access_token: "1111111115867080704-X513eNM39IduOomH1LSr4PJpp2gw3K:f7qe9L5c43uWj5fBupx8Oj9I5PGib79U0PFgMHOAfEwPy@tJlnPKxAG4lTEPeuLQKQnY6Za"
  client_id: "***masked***"
  display: "popup"
  expires: 1591279297.881
  expires_in: 0
  network: "twitter"
  oauth: {
    version: "1.0a",
    auth: "https://api.twitter.com/oauth/authenticate",
    request: "https://api.twitter.com/oauth/request_token",
    token: "https://api.twitter.com/oauth/access_token"
  },
  oauth_proxy: "https://auth-server.herokuapp.com/proxy"
  oauth_token: "1234854055867080704-X533eNM39IduOomH1L4r4PJpp2gw3a"
  oauth_token_secret: "f4qe9L5c43uWj5fB2px8Oj9I5PGib79U0PFgMHOAfEwPv"
  redirect_uri: "https://localhost:8081/"
  scope: "basic,email"
  screen_name: "Anonymous"
  state: ""
  user_id: "1133854055867080704"
},
network: "twitter"

I then try passing the access_token to my API server and use it as follows:

const client = new Twitter({
    consumer_key: config.twitterConsumerKey,
    consumer_secret: config.ConsumerSecret,
    bearer_token: token
});

const response = await client.get('users/show', {});

On doing the last call I get:

[ { code: 89, message: 'Invalid or expired token.' } ]

I did also try with account/verify_credentials:

const response = await client.get('account/verify_credentials', {
    include_entities: true,
    include_email: true
});

What is the right property I should be using from Twitter oauth, to pass to the Twitter client?

ajmas commented 5 years ago

Resolved the issue and sharing for anyone else, assuming the steps are correct:

You need to ensure you pass oauth_token and oauth_token_secret to your API server. Then the the constructor is:

const client = new Twitter({
  consumer_key: config.twitterConsumerKey,
  consumer_secret: config.twitterConsumerSecret,
  access_token_key: token,
  access_token_secret: tokenSecret
});

This then allowed me to call, the following:

const response = await client.get('account/verify_credentials', {
    include_entities: true,
    include_email: true
});

Note, from what I can tell there is no notion of 'scope' in Twitter oauth. This means requesting extra data, such as e-mail, needs to be done from the developer console.