How To: LinkedIn OAuth with Java

33 posts / 0 new
Last post
Pablo Fernandez's picture
LinkedIn Employee
Joined: 2009-11-23
Apr 6, 2010
How To: LinkedIn OAuth with Java

Hi, I've developed a java OAuth library that it's intended to work out-of-the-box with LinkedIn (and many other OAuth APIs). It's called Scribe and you can find more info here. Lets see how we can use Scribe to get the network updates for the current user for example.

The library comes with 'specs' for each supported API. These are step-by-step guides (like this one) to see the OAuth dance in action. Feel free to run those if you want, they live under the org.scribe.specs package.

Step Zero: Install Scribe Go to the Downloads page and grab the jar. You also need to have apache-commons-codec in your classpath. 1st Step: Configuration Scribe's main object it's initialized using a .properties file, which provides the necessary information to make authenticated calls. The library comes with some predefined .properties files for most common APIs that you usually have to tweak a bit to fit your needs. Let's see LinkedIn's standard file:

consumer.key=Your consumer keyconsumer.secret=Your consumer secretrequest.token.verb=POSTrequest.token.url=https://api.linkedin.com/uas/oauth/requestTokenaccess.token.verb=POSTaccess.token.url=https://api.linkedin.com/uas/oauth/accessTokencallback.url=oobscribe.equalizer=org.scribe.eq.LinkedInEqualizer

Most of this is self-explanatory. You only need to change the consumer.key, consumer.secret and callback.url if you don't wanna use Out Of Band OAuth.

 If you are curious about Scribe's Equalizers check this wikipage

Once you have your tuned properties, it's time to create the Scribe object 2nd Step: Creating Scribe's singleton object

Properties props = new Properties();FileInputStream fis = new FileInputStream("linkedin.properties");props.load(fis);Scribe scribe = Scribe.getInstance(props);

You have configured Scribe successfully 3rd Step: Get the Request Token This is easy, just do:

Token requestToken = scribe.getRequestToken();

The requestToken object has two methods: getToken() and getSecret(), they return the request_token and request_token_secret respectively. 4th Step: Authorize your Request Token Save the request_token_secret somewhere and go authenticate your request_token on the following URL:

https://api.linkedin.com/uas/oauth/authorize?oauth_token=<<copy your request_token here>>
 Warning: It seems that LinkedIn is changing the authorization page, check this entry and stay tuned (the former URL is said to be supported for a while, but its better to be safe than sorry)

Here 2 things can happen:

  • If you specified a callback URL, you'll be redirected there with the request_token and verifier as query-string parameters
  • If you are doing an Out Of Band Request, you will see the verifier (a number) on the screen.

Either way grab the verifier and let's go get the access_token! 5th Step: Get the Access Token Now you should have:

  • request_token: obtained in the scribe.getRequestToken() call
  • request_token_secret: obtained in the scribe.getRequestToken() call
  • verifier: obtained in step 4. Either by OOB or redirect
 Warning: If you are missing one of this 3 things, please re-check previous steps. 

It's time to change these for the access_token and access_token_secret, here we go:

Token requestToken = new Token("request_token", "request_token_secret");String verifier = "verifier";Token accessToken = scribe.getAccessToken(requestToken, verifier);

If everything is fine, accessToken will return your access_token and access_token_secret when you call getToken() and getSecret(), just like before. Last Step: Access the protected resource Enough authentication Now lets make the actual call:

Request request = new Request(Verb.GET, "http://api.linkedin.com/v1/people/~/network?count=50");   Token accessToken = new Token("access_token", "access_token_secret");   scribe.signRequest(request, accessToken);Response response = request.send(); //Do something with response.getBody()

Huray! We're done! Thanks for reading, hope this has helped you! Doubts? Comments? feel free to contact me via twitter. And happy hacking! -- Pablo Fernandez

Rohit Bansal's picture
Joined: 2010-07-25
Jul 25, 2010

hey,... thnx the code worked out absolutely fine...

Robert Willems of Brilman's picture
Joined: 2010-08-18
Aug 18, 2010

Thank you; the only thing i was missing was the equalizer thing. Found it thanks to this...

Robert Stone's picture
Joined: 2009-11-23
Sep 9, 2010

Hi Pablo,It looks like this tutorial is hopelussly outdated based on your latests release (1.0.1 at time of this note)

Pablo Fernandez's picture
LinkedIn Employee
Joined: 2009-11-23
Sep 9, 2010

Robert,Indeed. Scribe 1.0.1 was release just a few days ago, and the getting started on the github page is the only updated doc.I will update this eventually for the new version, if someone wants to do it, that would be awesome too! Thanks

Robert Stone's picture
Joined: 2009-11-23
Sep 9, 2010

I did it - would have no problem updating the tutorial however there's no "edit" button that I can spot :). I also discovered few issues with your code - for one I have a fix. Where is good place to communicate these to you?

Pablo Fernandez's picture
LinkedIn Employee
Joined: 2009-11-23
Sep 9, 2010

To create a new tutorial, you should go to the top and select "New" -> "Discussion".For fixes there are a few ways of doing it:BEST WAY:pull request via githubhttp://help.github.com/pull-requests/GOOD WAY:send me the patch to LastNameFirstName85@gmail.comBAD WAY:send me the code zipped to the previous email address.Thanks!

Robert Stone's picture
Joined: 2009-11-23
Sep 9, 2010

OK. Here's the new tutorial and I will log bugs on GitHub tomorrow

Suneet Kamath's picture
Joined: 2009-11-29
Sep 11, 2010

I used Selenium to automate step 4 for a java app.     public void getVerifier(String url, String user, String pswd) throws Exception {        Selenium sel = new DefaultSelenium("localhost", 4444, "*firefox",                "http://www.google.com");        sel.start();        sel.open(url);        sel.type("email-oauthAuthorizeForm", user);        sel.type("password-oauthAuthorizeForm", pswd);        sel.click("authorize");        sel.waitForPageToLoad("2500"); // tweak for slow connection speeds        verifier = sel.getText("xpath=//html/body/div/div[2]/div/div[2]/div");        sel.click("xpath=//html/body/div/div[2]/div/div[3]/ul/li/button");        sel.stop();     }Should work with the newer 1.1 Scribe API as well.Suneet

Joined: 2011-01-24
Jan 25, 2011

I have issues with 'scribe-1.1.0' on my Mac-OS-X. Please help.I get this error when I compile my sample code:Error-------YahooExample.java:11: cannot find symbolsymbol  : class Scribelocation: class YahooExample        Scribe scribe = Scribe.getInstance(props);My sample java code:------------------------------import java.util.Properties;import java.io.FileInputStream;public class YahooExample{    public static void main(String[] args)    {        Properties props = new Properties();        FileInputStream fis = new FileInputStream("yahoo.properties");        props.load(fis);        Scribe scribe = Scribe.getInstance(props);    }}My $CLASSPATH value is: ".:/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home:/Library/Tomcat/Home/lib/servlet-api.jar:/usr/local/scribe-1.1.0.jar:/usr/local/commons-codec-1.3.jar"My env----------1) I downloaded 'scribe-1.1.0.jar' and placed it under "/usr/local" directory.2) I also downloaded 'commons-codec-1.3.jar' and added it to the $CLASSPATH. The jar file is present in the proper location3) I have these settings in my env:     a) echo $JAVA_HOME          /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home     b) java -version          java version "1.6.0_15"     c) mvn -version          Apache Maven 2.2.1 (r801777; 2009-08-07 00:46:01+0530)          Java home: /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home          Java version: 1.6.0_15

kashif ilyas's picture
Joined: 2012-06-30
Jul 3, 2012

Hi Pablo, Can you please update me that either you have developed Blackberry version of scribe? It really love scribe and wants its support in Blackberry too.

John Moore's picture
Joined: 2012-08-10
Aug 13, 2012

Hi Pablo,
Just started using your library. Everything works great, but one question -- how do I store the accessToken for later use? As it works currently, I am running the user through the "authorize application" dance every time they want to log in to my site.

bhanuprasad saketi's picture
Joined: 2012-09-20
Sep 22, 2012

Hello...i can't understand what i am passing in callback url please tell me...please send me the total code

Kamyar Mohager's picture
LinkedIn Employee
Joined: 2012-04-04
Sep 24, 2012

The callback URL should be the URL you want LinkedIn to redirect your user to once they've authorized use of your application. You can either set this when configuring your application or passing it as a parameter during auth.

Thanks,
Kamyar

bhanuprasad saketi's picture
Joined: 2012-09-20
Sep 27, 2012

Thanks for the replay

Baskar Sikkayan's picture
Joined: 2011-08-17
Dec 1, 2012

Hi,

I use SCRIBE 1.3.2 and do the following to get the URL to redirect.

public String getAuthorizationURL(){
OAuthService service = new ServiceBuilder()
.provider(LinkedInApi.class)
.apiKey("API_KEY")
.apiSecret("SECRET_KEY")
.callback("CALL_BACK_URL")
.build();

Token requestToken = service.getRequestToken();
return service.getAuthorizationUrl(requestToken);
}

I then, redirected the above URL in my servlet.

In the callback url, i am getting the verifier and trying to get the response.
Is it valid. Also, Can i store this verifier for this user in my system and use this for future API calls?

public void getData(String verifier){
OAuthService service = new ServiceBuilder()
.provider(LinkedInApi.class)
.apiKey("95di5qodoqlp")
.apiSecret("FSrpeuK7XW0VGmZI")
.callback("http://localhost:18080/skillthirst/usr/socal/linkedin")
.build();

Token requestToken = service.getRequestToken();
Verifier verifierObj = new Verifier(verifier);
Token accessToken = service.getAccessToken(requestToken, verifierObj);

OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println(response.getBody());

}

Thanks,
Baskar.S

Shikha A. Sehgal's picture
LinkedIn Employee
Joined: 2012-07-27
Dec 3, 2012

Baskar,

The steps that you described look good. You can store the verifier but each time you want to make an API calls you will have to exchange the verifier for the accessToken that you get in the step right after. A more efficient approach will be storing the accessToken instead. You can then use this accessToken to make all the future API calls for that particular user.

afnan asghar's picture
Joined: 2012-12-18
Dec 18, 2012

google
yahoo
msn

afnan asghar's picture
Joined: 2012-12-18
Dec 18, 2012

wwww.afnanparfum.com

Vladimir Bazarsky's picture
Joined: 2012-01-19
Dec 19, 2012

Hi Pablo,

Is there any tricks about callBackUrl ?
I need it to be dynamically passed to the LinkedIn, b/c for every user I have different callBack.
I use common callBack upon initialization.
Then for every LinkedIn authorization I pass relevant callBack.
I tried different ways of doing it.
Reinitializing for every authorization,
Resetting callbackUrl for OAuthAccessor,
Passing in signed parameters.

Nothing seems to be working.
Still upon cancellation, I am redirected to static ( first time initialized ) url.
First initialization is autowired with Spring.

Any ideas / recommendations ?
Thanks,
VB

Ming Gao's picture
Joined: 2012-11-01
Dec 27, 2012

Hi,
I am stuck here, and could not find a way to store the accessToken.

In the Scribe Java example, the call is made by :
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
OAuthService service.signRequest(accessToken, request);
Response response = request.send();

If i stored "accessToken" , how about the service object and others? Is it possbile you give us some sample source code?

== Edited ==
OK, i think i got the way to make it work. Anyone who wants the example code. Can send me an email at mgao@avaya.com.

George

Sambath kumar's picture
Joined: 2013-01-18
Jan 23, 2013

Hi Ming,
Plz paste the sample code in the thread.

Joined: 2013-01-29
Jan 30, 2013

Hi Pablo,

Is there any inbuilt function available to refresh access-token and get new /old access-token along with extended expiry date ?

Thanks,
Remya

Deepak Gangore's picture
Joined: 2012-09-20
Jan 30, 2013

hi all,

I am using scribe for developing linkedin application for my website. Please tell me how to get access token without using verifier or OOB. I want simply to redirect my one of the page where i can get access token and secret after authentication.

Thanks in advance
Deepak Gangore

Nihal Bhagchandani's picture
Joined: 2013-01-29
Feb 4, 2013

Hi Shikha,

as suggested by you, I stored the accessToken and tried to use it for second call, but I am getting error "net.oauth.OAuthProblemException: HTTP/1.1 401 Unauthorized".

Bhabani Shankar Panda's picture
Joined: 2013-02-19
Mar 17, 2013

Hi Pablo, Thanks for the post. I am getting Access to network denied message in last step. Can't figure out what is the problem. Thaks in advance for any help.

Shikha A. Sehgal's picture
LinkedIn Employee
Joined: 2012-07-27
Mar 18, 2013

hey Nihal:

Did you use the accessToken after it was expired i.e. after 60 days of its generation? If so, then you will have to generate a new accessToken.

Shikha A. Sehgal's picture
LinkedIn Employee
Joined: 2012-07-27
Mar 18, 2013

hey bhabani:

Can you confirm that you are using the rw_nus member permissions as explained in this doc. You will need this member permissions in order to retrieve network updates.

Bhabani Shankar Panda's picture
Joined: 2013-02-19
Mar 20, 2013

Hi Shikha,
Thanks for replying. I am using Apache Amber using java for oauth 2.0 call. And the code generated is a fresh one. And during the code generation I am granting the permission.
But in second step to create the Access Token I am getting error. Can you please help me getting some sample code to do this in java.
Also tried with Scribe and getting same problem in creating Access Token

Shikha A. Sehgal's picture
LinkedIn Employee
Joined: 2012-07-27
Mar 20, 2013

Our Authentication doc clearly explains how you can authenticate your application using OAuth 2.0 and also get the required member permissions. The calls explained in that doc are very generic and can be adopted to any language. If you are getting the "access denied" error then most likely the issue can be in the way you are adding the member permissions query parameters to your call.

Joined: 2013-03-06
Mar 21, 2013

Dear Pablo,
I have done all those as you said on your first comment...
" java.io.FileNotFoundException: linkedin.properties"
Please help me out..

Joined: 2013-07-08
Jul 11, 2013

how to make the access token to be valid for long period in linkedin

Sudeep Bansal's picture
Joined: 2013-11-25
Nov 27, 2013

Dear Shikha,

I need to get the email-address of the user contacts. Can you help me out...
as after using the connection parameter i received this
<connections>
<person>
<id>gnGBSIP-PY</id>
<first-name>????</first-name>
<last-name>???????</last-name>
<headline>Sr. Facility Executive at Tech Mahindra</headline>
<picture-url>http://m.c.lnkd.licdn.com/mpr/mprx/0_U-uG0hh1NzpO0QhGJrpl0C9tN9Vm1LhGMnZg0_bawKaY2TcCcqyali1hsRslKG3asAmprXJutW2j</picture-url>
<api-standard-profile-request>
<url>http://api.linkedin.com/v1/people/gnGBSIP-PY</url>
<headers total="1">
<http-header>
<name>x-li-auth-token</name>
<value>name:54AQ</value>
</http-header>
</headers>
</api-standard-profile-request>
<site-standard-profile-request>
<url>http://www.linkedin.com/profile/view?id=44440955&amp;authType=name&amp;authToken=54AQ&amp;trk=api*a3479381*s3552171*</url>
</site-standard-profile-request>
<location>
<name>New Delhi Area, India</name>
<country>
<code>in</code>
</country>
</location>
<industry>Information Technology and Services</industry>
</person>
</connections>

Can you help me out from where i can get the email address too....