I am trying to work with Twitter APIs to build a web application using ExpressJS. I am using PassportJS for Twitter authentication. After logging in, I tried making a call to the GET friends/ids endpoint and I was getting { errors: [ { code: 32, message: 'Could not authenticate you.' } ] }
. I am using the request npm module to make calls to the endpoint. I have built everything necessary, especially the header string for Authorization, but that error is all that comes back. Here's what I have so far:
somefile.js
const request = require('request')
const crypto = require('crypto')
const Math = require('mathjs')
const oauthConsumerKey = process.env.CONSUMER_KEY
const oauthConsumerSecret = process.env.CONSUMER_SECRET
const oauthNonce = crypto.randomBytes(16).toString('hex')
const oauthSignatureMethod = 'HMAC-SHA1'
const oauthTimestamp = Math.floor(Date.now() / 1000)
const oauthVersion = '1.0'
const httpMethod = 'GET'
// Build parameter string
const buildSignatureParameterString = (token) => {
const oauthToken = encodeURIComponent(token)
const signatureParameterString = `include_entities=true&oauth_consumer_key=${oauthConsumerKey}&oauth_nonce=${oauthNonce}&oauth_signature_method=${oauthSignatureMethod}&oauth_timestamp=${oauthTimestamp}&oauth_token=${oauthToken}&oauth_version=${oauthVersion}`
return signatureParameterString
}
// Build signing key
const buildSigningKey = (tokenSecret) => {
const signingKey = `${encodeURIComponent(oauthConsumerSecret)}&${encodeURIComponent(tokenSecret)}`
return signingKey
}
// GET friends/ids
const getFriends = (id, token, signParamString, signingKey) => {
const oauthToken = encodeURIComponent(token)
const url = `https://api.twitter.com/1.1/friends/ids.json?user_id=${id}`
const signatureBaseString = `${httpMethod}&${encodeURIComponent(url)}&${encodeURIComponent(signParamString)}`
const oauthSignature = encodeURIComponent(crypto.createHmac('sha1', signingKey).update(signatureBaseString).digest('base64'))
const authHeaderString = `OAuth oauth_consumer_key="${oauthConsumerKey}",oauth_nonce="${oauthNonce}",oauth_signature="${oauthSignature}",oauth_signature_method="${oauthSignatureMethod}",oauth_timestamp="${oauthTimestamp}",oauth_token="${oauthToken}",oauth_version="${oauthVersion}"`
console.log(authHeaderString)
const options = {
url,
json: true,
headers: {
'Authorization': authHeaderString
}
}
request(options, (error, response) => {
if(error) return console.log(error)
console.log(`Status code: ${response.statusCode}\n`)
console.log(response.body)
})
}
module.exports = { buildSignatureParameterString, buildSigningKey, getFriends }
index.js (entry point)
const { buildSignatureParameterString, buildSigningKey, getFriends } = require('./utils/unfollowers')
passport.use(new TwitterStrategy({
consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
callbackURL: `http://${process.env.BASE_URL}:${process.env.PORT}/auth/twitter/callback`,
}, (token, tokenSecret, profile, callback) => {
profile.token = token
profile.tokenSecret = tokenSecret
return callback(null, profile)
}))
...
app.get('/friendsIDs', require('connect-ensure-login').ensureLoggedIn('/'), (req, res) => {
const signParamString = buildSignatureParameterString(req.user.token)
const signingKey = buildSigningKey(req.user.tokenSecret)
getFriendsIDs(req.user.id, req.user.token, signParamString, signingKey)
console.log(`Authorization: ${req.headers.authorization}`)
const { screen_name: screenName, followers_count: followers, friends_count: following } = req.user._json
res.render('friendsIDs', { screenName, followers, following })
})
Here's what I found out:
console.log(
Authorization: ${req.headers.authorization})
returns undefined
and I don't understand why. I think I just need a way to set the Authorization header and I'll get an actual response. I know the request
module supports OAUTH1.0. In fact, I have used it and it works. I just wanna know what's behind my error. Thanks for the help!