Node.js OAuth1.0 and OAuth2.0: Twitter API v1.1 Examples

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.

Node.js OAuth

Node.js OAuth

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):

  1. Your Twitter application key, a.k.a., consumer key
  2. Your Twitter secret key
  3. User token for your app
  4. 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.

Tools

18 thoughts on “Node.js OAuth1.0 and OAuth2.0: Twitter API v1.1 Examples

  1. MarB

    Hi, great article.

    I’m trying to send result of user timeline to Angular with OAuth 1. I can log timeline on backend ok, but I can’t return the JSON to Angular controller.

    I tried “res.send(data)” which returns: TypeError: Object # has no method ‘send’

    Patience please, I’m new to javascript, any help appreciated. Thanks

  2. Azat Post author

    Hi Ellis,

    Thanks for your questions. Others might wonder about it as well.

    Protected url is basically a placeholder for URL that you try to get access to (usually on behalf of your users), e.g., getting Twitter user profile information. Most service providers’ APIs require OAuth to use their API endpoints which makes them protected.

  3. EllisGL

    Stupid question probably, but I noticed that you have ‘protected url’ in this code, and after tracing some stuff down, what is the ‘protected url’ supposed to be?

    I’m also trying to use to authenticate users, not myself – which I’m not sure if this code does that, am I wrong?

  4. Chris B

    Here’s a App Auth (OA2) example I wanted to see what was behind the scenes without the libraries..

    function T(cons_key, cons_secret){
    return {
    r: require(‘request’),
    tok: null,
    api: function(name, cb){
    var th = this;
    if(!this.tok){
    this.r.post({url: ‘https://api.twitter.com/oauth2/token/’,
    headers: {Authorization: ‘Basic ‘ + new Buffer(cons_key +’:'+ cons_secret).toString(‘base64′)},
    form: {grant_type: ‘client_credentials’}
    }, function(e,r,b){th.tok=JSON.parse(b).access_token; th.api(name, cb)});
    return;
    }
    this.r.get({
    url: ‘https://api.twitter.com/1.1/search/tweets.json?q=javascript’,
    headers: {Authorization: ‘Bearer ‘ + th.tok}
    }, function(e,r,b){cb(JSON.parse(b))})
    }
    }
    }
    var tw = T(‘consumer_key’, ‘consumer_secret’);
    tw.api(‘search/tweets.json?q=javascript’, function(r){
    console.log(r)
    });

  5. Aaron

    On OAuth2, are we supposed to use exports.OAuth2.prototype._request as public api? The REST convenience methods are curiously missing. As are comments no _request. I would love to contribute. Sad about pull requests being ignored.

  6. Ciaran

    Thanks for this, looks like a great resource, would be great to fold some of these examples back into the module’s wiki pages ?

  7. Ciaran

    Thanks for this, some good resources here, would be even better to fold them back into the wiki on the oauth module site ;)

  8. dot

    Oh sorry my bad, i was googling around all day trying to find out to do oAuth for my app and also trying to retrieve a user’s twitter home feed, it totally passed by me that you are using node.js. I am fairly new to this, so to include node.js how would I do this? Would i just include node.js in a javascript and include it in my html?Please let me know. I appreciate your help, thanks.

  9. dot

    Now I get OAuth is undefined. Here is my code, will u b able to identify what I am doing wrong? Also twitter doesn’t support OAuth2.0 yet officially does it?

    Twitter JQM

    var OAuth2 = null;

    function load(){

    alert(‘page is loaded’);
    OAuth2 = OAuth.OAuth2;

    var twitterConsumerKey = ’5BX4tmZJ47hPUa5zOESIog’;
    var twitterConsumerSecret = ‘w1vJDxxHZB4IL4inkIWLA18InRy74gaMVflzKChbN0′;
    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); }); });
    }

  10. DOT

    Hi

    I am trying the oAuth 2 code for my mobile web app using javascript.
    but i get the OAuth2 is undefined error. Why would that be?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>