Recently we had to work on modification to accommodate Twitter API v1.1. The main difference between Twitter API v1.1 and, soon to be deprecated, Twitter API v1.0 is that most of the REST API endpoints now require user or application context. In other words, each call needs to be performed via OAuth 1.0A or OAuth 2.0 authentication.
At Storify we run everything on Node.js so it was natural that we used oauth module by Ciaran Jessup: NPM and GitHub. It’s mature and supports all the needed functionality but lacks any kind of examples and/or interface documentation.
Here are the examples of calling Twitter API v1.1, and a list of methods. I hope that nobody will have to dig through the oauth module source code anymore!
OAuth 1.0
Let start with a good old OAuth 1.0A. You’ll need four values to make this type of a request to Twitter API v1.1 (or any other service):
- Your Twitter application key, a.k.a., consumer key
- Your Twitter secret key
- User token for your app
- User secret for your app
All four of them can be obtained for your own apps at dev.twitter.com. In case that the user is not youself, you’ll need to perform 3-legged OAuth, or Sign in with Twitter, or something else.
Next we create oauth object with parameters, and call get()
function to fetch a secured resource. Behind the scene get()
function constructs unique values for the request header — Authorization header. The method encrypts URL, timestamp, application and other information in a signature. So the same header won’t work for another URL or after a specific time window.
var OAuth = require('OAuth');
var oauth = new OAuth.OAuth(
'https://api.twitter.com/oauth/request_token',
'https://api.twitter.com/oauth/access_token',
'your Twitter application consumer key',
'your Twitter application secret',
'1.0A',
null,
'HMAC-SHA1'
);
oauth.get(
'https://api.twitter.com/1.1/trends/place.json?id=23424977',
'your user token for this app',
//you can get it at dev.twitter.com for your own apps
'your user secret for this app',
//you can get it at dev.twitter.com for your own apps
function (e, data, res){
if (e) console.error(e);
console.log(require('util').inspect(data));
done();
});
});
OAuth Echo
OAuth Echo is similar to OAuth 1.0. If you’re a Delegator (service to which requests to Service Provider are delegated by Consumer) all you need to do is just pass the value of x-verify-credentials-authorization header to the Service Provider in Authorization header. Twitter has a good graphics on OAuth Echo.
There is OAuthEcho object which inherits must of its methods from normal OAuth class. In case if you want to write Consumer code (or for functional tests, in our case Storify is the delegator) and you need x-verify-credentials-authorization/Authorization header values, there is a authHeader
method. If we look at it, we can easily reconstruct the headers with internal methods of oauth module such as _prepareParameters()
and _buildAuthorizationHeaders()
. Here is a function that will give us required values based on URL (remember that URL is a part of Authorization header):
function getEchoAuth(url) {
//helper to construct echo/oauth headers from URL
var oauth = new OAuth('https://api.twitter.com/oauth/request_token',
'https://api.twitter.com/oauth/access_token',
"AAAAAAAAAAAAAAAAAAAA",
//test app token
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
//test app secret
'1.0A',
null,
'HMAC-SHA1');
var orderedParams = oauth._prepareParameters(
"1111111111-AAAAAA", //test user token
"AAAAAAAAAAAAAAAAAAAAAAA", //test user secret
"GET",
url
);
return oauth._buildAuthorizationHeaders(orderedParams);
}
From your consumer code you can maker request with superagent or other http client library (e.g., node.js core http module’s http.request):
var request = require('super agent');
request.post('your delegator api url')
.send({...})
//your json data
.set(
'x-auth-service-provider',
'https://api.twitter.com/1.1/account/verify_credentials.json')
.set(
'x-verify-credentials-authorization',
getEchoAuth("https://api.twitter.com/1.1/account/verify_credentials.json"))
.end(function(res){console.log(res.body)});
OAuth2
OAuth 2.0 is a breeze to use comparing to the other authentication methods. Some argue that it’s not as secure, so make sure that you use SSL and HTTPS for all requests.
var OAuth2 = OAuth.OAuth2;
var twitterConsumerKey = 'your key';
var twitterConsumerSecret = 'your secret';
var oauth2 = new OAuth2(
twitterconsumerKey,
twitterConsumerSecret,
'https://api.twitter.com/',
null,
'oauth2/token',
null);
oauth2.getOAuthAccessToken(
'',
{'grant_type':'client_credentials'},
function (e, access_token, refresh_token, results){
console.log('bearer: ',access_token);
oauth2.get('protected url',
access_token, function(e,data,res) {
if (e) return callback(e, null);
if (res.statusCode!=200)
return callback(new Error(
'OAuth2 request failed: '+
res.statusCode),null);
try {
data = JSON.parse(data);
}
catch (e){
return callback(e, null);
}
return callback(e, data);
});
});
Please note the JSON.parse()
function, oauth module returns string, not a JavaScript object.
Consumers of OAuth2 don’t need to fetch the bearer/access token for every request. It’s okay to do it once and save value in the database. Therefore, we can make requests to protected resources (i.e. Twitter API v.1.1) with only one secret password. For more information check out Twitter application only auth.
Node.js oauth API
Node.js oauth OAuth
oauth.OAuth()
Parameters:
- requestUrl
- accessUrl
- consumerKey
- consumerSecret
- version
- authorize_callback
- signatureMethod
- nonceSize
- customHeaders
Node.js oauth OAuthEcho
oauth.OAuthEcho()
Parameters:
- realm
- verify_credentials
- consumerKey
- consumerSecret
- version
- signatureMethod
- nonceSize
- customHeaders
OAuthEcho sharers the same methods as OAuth
Node.js oauth Methods
Secure HTTP request methods for OAuth and OAuthEcho classes:
OAuth.get()
Parameters:
- url
- oauth_token
- oauth_token_secret
- callback
OAuth.delete()
Parameters:
- url
- oauth_token
- oauth_token_secret
- callback
OAuth.put()
Parameters:
- url
- oauth_token
- oauth_token_secret
- post_body
- post_content_type
- callback
OAuth.post()
Parameters:
- url
- oauth_token
- oauth_token_secret
- post_body
- post_content_type
- callback
https://github.com/ciaranj/node-oauth/blob/master/lib/oauth.js
Node.js oauth OAuth2
OAuth2 Class
OAuth2()
Parameters:
- clientId
- clientSecret
- baseSite
- authorizePath
- accessTokenPath
- customHeaders
OAuth2.getOAuthAccessToken()
Parameters:
- code
- params
- callback
OAuth2.get()
Parameters:
- url
- access_token
- callback
https://github.com/ciaranj/node-oauth/blob/master/lib/oauth2.js
The authors of node.js oauth did a great job but currently there are 32 open pull requests (mine is one of them) and it makes me sad. Please let them know that we care about improving Node.js ecosystem of modules and developers community!
UPDATE: Pull request was successfully merged!
Useful Twitter API v1.1 Resources
Just because they are vast and not always easy to find.
- Changes to the ‘Sign in with Twitter’ flow
- Introducing new metadata for Tweets
- REST API v1.1 Limits per window by resource
- REST API v1.1 Resources
- Creating a signature
- OAuth Echo
- Authorizing a request
- Implementing Sign in with Twitter
- xAuth
- 3-legged authorization
- Obtaining access tokens
- Application-only authentication