There are a number of prebuilt solutions to do authentication using Twitter as an identity provider (Sign-in with Twitter). This is OAuth user authentication. But if your application needs to do tasks like post a tweet on behalf of a user, you need to use Twitter OAuth user authorization to allow your users to authorize your app.
In this guide, I'll explain how to do Twitter authorization as simply as possible.
In a recent app I built, I needed to enable the users to authorize the app to use Twitter on their behalf. I found Twitter documentation to be confusing and inaccurate to say the least.
After spending way too much time pouring over the API documentation, I got the feeling that Twitter is intentionally trying to make it difficult for developers to use. I doubt this is actually true, but a quick search shows Twitter has been struggling with developer relations for nearly 10 years.
Check out this section from the developer docs.
Rather than standardizing on terminology and updating their documentation, they put in a clarification section that includes what appears to be a copy-paste typo.
In any case, I didn't find much help elsewhere on the web either, so in this article I'll share how to do Twitter authorization in a simple and clear way.
An overview of the steps needed to get an authorization token
Your app requests a key from Twitter and tells Twitter where you want the user redirected to after authorization.
Your app uses this key to construct a twitter.com URL and redirects the user to it.
The user authorizes your app on the Twitter website and is then redirected back to your app.
Your app collects verifier information from this redirect.
Your app uses all this information to request the actual authorization token from Twitter.
Your app can now use this token with the Twitter API to make posts and other "user context" tasks on behalf of your users.
A closer look at each of these five steps
Your app first requests an
oath_token
andoauth_token_secret
from Twitter. Your app does this by making a POST request to Twitter'soauth/request_token
endpoint. While doing this, your app also provides Twitter with acallback
URL pointing back to your app.Your app temporarily stores both the
oauth_token
andoauth_token_secret
and then uses theoauth_token
to construct a twitter.com url that looks like this:
https://api.twitter.com/oauth/authorize?oauth_token=NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0
Your app redirects the user to this twitter.com url and the user is given the opportunity to authorize your app. As soon as the user authorizes your app, Twitter redirects the user back to your app using the
callback
URL you provided in step 1.Your app's
callback
URL expects two pieces of information from Twitter in the form of url encoded parameters,oauth_token
andoauth_verifier
. Theoauth_token
is the same token your app received in step 1 and can be used to look up the previously storedoauth_token_secret
.Your app now has
oauth_token
,oauth_token_secret
, andoauth_verifier
. It uses these three pieces of information to make another POST request to Twitter. This time it uses theoauth/access_token
endpoint. The response to this request contains the finaloauth_token
andoauth_token_secret
.
This final oauth_token
and oauth_token_secret
are stored securely associated with the user. Your app can now use the Twitter API on behalf of the user.
Note: It is important to understand that there are two each of
oauth_token
andoauth_token_secret
. The first is temporary and is requested in step 1 and used in step 2 and step 5. The second is requested in step 5 and is the final token needed to use the Twitter API.
Twitter libraries
Let's look at how this can be implemented. We'll be using Node on the server and a library that will take care of some of the HTTP work for us.
There are quite a few dead Twitter libraries out there. Twitter itself currently links to unmaintained libraries like this:
twitter-node-client
The node-twitter library is not linked from Twitter but is maintained and works for most of the Twitter API. However, it does not work to request keys from Twitter on behalf of your users. It prepends an API version string to the request path, which isn't wanted for the OAuth URLs. Additionally, despite the documentation, Twitter's auth/request_token
endpoint doesn't return JSON, it returns url-encoded form data. Node-twitter assumes response bodies are always JSON and it crashes with a parse error.
So we'll go slightly less specialized and use the excellent request HTTP client. Actually, we'll use the request-promise-native version of the same thing.
The same five steps explained in code
This should be viewed as pseudo-code in that it is just the important bits pulled out of async functions. It represents only the happy path with all error checking, refactoring and testing removed.
Step One
The first (and every) request you'll make to Twitter requires your app's "Consumer API keys." You can get these from the "Keys and tokens" tab in your app page of the Twitter developer dashboard. Provide the url-encoded callback
URL that will receive oauth_token
and oauth_verifier
in step four. This URL needs to be whitelisted in the "App details" tab of the Twitter dashboard.
const request = require('request-promise-native')
const encodeUrl = require('encodeurl')
const options = {
headers: { Accept: '*/*', Connection: 'close', 'User-Agent': 'node-twitter/1' },
oauth: {
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
callback: encodeUrl('https://your-app.com/twitter-callback'),
},
url: `https://api.twitter.com/oauth/request_token`,
}
const result = await request.post(options)
Step Two
Parsing the result will give us oauth_token
and oauth_token_secret
. Store these in your database associated with the user for later retrieval after the user has authorized your app.
const responseData = queryString.parse(result)
console.log(responseData)
//=> { oauth_token: 'NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0', oauth_token_secret: 'veNRnAWe6inFuo8o2u8SLLZLjolYDmDP7SzL0YfYI' }
const tmpOauthToken = responseData.oauth_token
const tmpOauthTokenSecret = responseData.oauth_token_secret
Step Three
Create a twitter.com URL and redirect the user to it. They are given
the opportunity to authorize your app. As soon as your app is authorized, Twitter redirects the user back to your app using the callback
URL you provided in step one.
const redirectUrl =
`https://api.twitter.com/oauth/authorize?oauth_token=${tmpOauthToken}`
Step Four
Your app's callback
URL expects two pieces of information from Twitter in the form of url encoded parameters, oauth_token
and oauth_verifier
. The oauth_token
is the same token your app received in step 1 and can be used to look up the previously stored oauth_token_secret
. The URL will look something like this: https://your-app.com/twitter-callback?oauth_token=NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0&oauth_verifier=uw7NjWHT6OJ1MpJOXsHfNxoAhPKpgI8BlYDhxEjIBY
const queryString = require('query-string')
console.log(location.search)
//=> 'oauth_token=NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0&oauth_verifier=uw7NjWHT6OJ1MpJOXsHfNxoAhPKpgI8BlYDhxEjIBY'
const tokens = queryString.parse(location.search)
const tmpOauthToken = tokens.oauth_token
const oauthVerifier = tokens.oauth_verifier
Fetch the tmpOauthTokenSecret
value that you received in step one and stored in the database in step two. Use the tmpOauthToken
value from above to do this.
Step Five
Your app now has oauth_token
, oauth_token_secret
, and oauth_verifier
. Use these three pieces of information to make another POST request to Twitter. This time it uses the oauth/access_token
endpoint. The response to this request contains the final oauth_token
and oauth_token_secret
. Store this final oauth_token
and oauth_token_secret
in the database securely associated with the user.
const options = {
headers: { Accept: '*/*', Connection: 'close', 'User-Agent': 'node-twitter/1' },
oauth: {
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
token: tmpOauthToken,
token_secret: tmpOauthTokenSecret,
verifier: oauthVerifier,
},
url: `https://api.twitter.com/oauth/access_token`,
}
const result = await request.post(options)
const responseData = queryString.parse(result)
// Final token to be stored with the user
const userOauthToken = responseData.oauth_token
const userOauthTokenSecret = responseData.oauth_token_secret
Using the results
Your app can now use the Twitter API on behalf of the user. This can be done with a Node Twitter client like this:
const Twitter = require('twitter')
const client = new Twitter({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token_key: userOauthToken,
access_token_secret: userOauthTokenSecret
})
const result = await client.post('statuses/update', {
status: 'All your Twitter are belong to us! (you did give us permission)'
})
Top comments (0)