Total Pageviews

Saturday, January 5, 2013

LINKEDIN api call using NODE.JS OAUTH module


Wish you all my readers a very happy and prosperous new year 2013.

We usually say let’s forget the past and start with a new beginning. However personally I feel this past year will be never forgotten. The year 2012, saw a remarkable paradigm shift with Microsoft’s whole new Windows 8 and Surface technologies.  On the Azure front, many cool features keep coming, whether it is HadoopOnAzure or Azure Mobile Service, Microsoft kept delivering the best that it could. The remarkable thing for me is when Microsoft started joining hands with open source communities like Hadoop. Open source community contributors have added value to Microsoft technologies. Be it support of Node.JS in Azure Mobile service or HDInsight using Hadoop framework, with every new feature a new opportunity opened for consumers and industries.

Let me now focus on today’s topic where I will be talking about a Proof of concept that will help you to use the code as per your requirement with ease. I have used LinkedIn apis through Node.JS scripts in order to make an LinkedIn analytical app. LinkedIn provides some cool apis which can be used to create apps like search for a job for this position, or analyze my network updates and highlight only those updates which have the term ‘Azure’ or ‘Node.JS’ etc. All the apis can be found here.

I will keep the imagination part for you and start with the technical stuff. In order to use LinkedIn APIs one have to be an authorized user. Linkedin, Facebook, Google and many more uses OAuth authentication for authorizing users. Having said that, I will like to mention that some experts believe that OAuth is not an authentication protocol. An interesting blog post by Vittorio has details for the same. Nevertheless let’s consider OAuth to be an authentication protocol for this blog.

Now to use LinkedIn apis we were in need to provide proper OAuth access tokens with our api requests. Following diagram shows how we are accomplishing the trust relationship between the client and LinkedIn and then using the apis.




Approach

1.       Create an app by signing at http://developer.linkedin.com/

2.       Once you create the app click on the application name
3.       Take a note of API key and secret key

4.       Node.JS initializes a server listening on a specified port. Here I have used express node to initiate a server
5.       Client request for the OAuth authentication token by request to request token url of LinkedIn https://api.linkedin.com/uas/oauth/requestToken. Client provide the API key and secret key in with the request.
6.       Server responds back with a token.
7.       Now the Node.JS redirects the response to the LinkedIn url https://www.linkedin.com/uas/oauth/authorize?oauth_token="+oauth_token with the oauth_token and asks the user to put his/her credentials.
8.       After successful login LinkedIn responds back with a OAuth verifier.
9.       Now the Node.JS uses this OAuth access token , OAuth secret token and the OAuth verifier to request the LinkedIn apis
Following is the server side script
Server.js
var express = require('express'), // Using the express module to create the server
                         OAuth = require('oauth').OAuth, // Using OAuth Node.JS module to get the authentication token from LinkedIn
                // Setup the Express.js server
                var app = express();
                app.use(express.logger());
               app.use(express.bodyParser());
               app.use(express.cookieParser());
       app.use(express.session({
                        secret: "skjghskdjfhbqigohqdiouk"
}));
//Root page
app.get('/', function(req, res){
if(!req.session.oauth_access_token) {
                        //If the user does not have the OAuth access token then redirect the response to another url
                                res.redirect("/linkedin_login");
}
});

// Request an OAuth Request Token, and redirects the user to authorize it
          app.get('/linkedin_login', function(req, res) {    
           var getRequestTokenUrl = "https://api.linkedin.com/uas/oauth/requestToken";    
           var oa = new OAuth(getRequestTokenUrl,
                                       "https://api.linkedin.com/uas/oauth/accessToken",
                                       "<<API KEY>>",
                                       "<<SECRET KEY>>",
                                       "1.0",
                                        "http://localhost:3000/linkedin_callback"+( req.param('action') && req.param('action') != "" ? "?action="+querystring.escape(req.param('action')) : "" ), // the callback url where LinkedIn OAuth secret token will be sent

                                          "HMAC-SHA1");

                        oa.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results){
                          if(error) {
                                                console.log('error');
                                }
                          else {
                                                // store the tokens in the session
                                                req.session.oa = oa;
                                                req.session.oauth_token = oauth_token;
                                                req.session.oauth_token_secret = oauth_token_secret;


                                                // redirect the user to authorize the token                                                  res.redirect("https://www.linkedin.com/uas/oauth/authorize?oauth_token="+oauth_token);
                          }
                        })
});

// Callback for the authorization page
app.get('/linkedin_callback', function(req, res) {                              
                        // get the OAuth access token with the 'oauth_verifier' that we received
                        req.session.oauth.verifier = req.param('oauth_verifier');

                        var oa = new OAuth(req.session.oa._requestUrl,
                                           req.session.oa._accessUrl,
                                          req.session.oa._consumerKey,
                                          req.session.oa._consumerSecret,
                                          req.session.oa._version,
                                          req.session.oa._authorize_callback,
                                          req.session.oa._signatureMethod);            
                         console.log(oa);     
                    
    oa.getOAuthAccessToken(
                                req.session.oauth_token,
                                req.session.oauth_token_secret,
                                req.param('oauth_verifier'),
                                function(error, oauth_access_token, oauth_access_token_secret, results)    {                                     
                                              if(error) {
                                                                console.log('error');
                                                }
                                                else {

                                                               // store the access token in the session
                                                                req.session.oauth_access_token = oauth_access_token;
                                                                req.session.oauth_access_token_secret = oauth_access_token_secret;

                                                                //res.redirect("https://www.linkedin.com/uas/oauth/authenticate?oauth_token=" + oauth_access_token);
                                                                res.redirect((req.param('action') && req.param('action') != "") ? req.param('action') : "/linkedin_track");
                                                }
                        });  
});

app.get('/linkedin_track', function(req, res) {
                        var oa = new OAuth(req.session.oa._requestUrl,
                                          req.session.oa._accessUrl,
                                          req.session.oa._consumerKey,
                                          req.session.oa._consumerSecret,
                                          req.session.oa._version,
                                          req.session.oa._authorize_callback,
                                          req.session.oa._signatureMethod);            
    console.log(oa);

                        oa.getProtectedResource(

                        //Calling the people search api to know who are my connections who directly or indirectly are connected to Azure           
                                "http://api.linkedin.com/v1/people-search?keywords=Azure",
                                "GET",
                                req.session.oauth_access_token,
                                req.session.oauth_access_token_secret,
                                function (error, data, response) {
                                                //var feed = JSON.parse(data);
                                                res.send(data);
                                                });
});                   
app.listen(3000);
console.log("listening on http://localhost:3000");

Output

1.       Enter http://localhost:3000/ at your browser url

2.       You will be redirected to the LinkedIn authorization url
 


3.       On clicking continue it will respond back with the JSON result of my connections who are using azure
 

That’s it ……Hope this blog will help you to use Node.JS scripts and easily develop your own analytical tools.
Have a great year ahead !!! :)


 

2 comments:

  1. Thanks this was helpful.. few edits:
    // get the OAuth access token with the 'oauth_verifier' that we received
    req.session.oauth.verifier = req.param('oauth_verifier');
    should be:
    // get the OAuth access token with the 'oauth_verifier' that we received
    req.session.oauth_token.verifier = req.query.oauth_verifier;

    and var getRequestTokenUrl = "https://api.linkedin.com/uas/oauth/requestToken" should have scope ex:;
    var getRequestTokenUrl = "https://api.linkedin.com/uas/oauth/requestToken?scope=r_network";

    ReplyDelete