Rockstar Engineering

Quick and Dirty Twitter4j OAuth for Web Apps

Posted in Uncategorized by Jose Asuncion on September 3, 2009

This simple tutorial is a result of my trying to oauth to twitter using Twitter4j. It is actually part of my thesis in my university, a small functionality in a much wider application.

Anyway, I have been googling tutorials on how to use Twitter4j in a web app but I haven’t found much. The Twitter4j has examples but most of them in are written in a main method. I did find some leads in the Twitter4j google group and much to my surprise, the key to accessing data in Twitter using Twitter4j/Oauth is knowing how Oauth works in the first place.

This tutorial isn’t about how to use the oauth protocol there are many resources in the net about that .

Try here, here and well, here.

Although this code works, it might not be the right way to use Twitter4j and Oauth. It might not be optimized and it’s definitely not the best way. It’s actually riddled with bad practices! Although in my real app, I have refactored those code smells already.

UPDATE: Here’s a refactored solution that I did.

Another thing, I have yet to address why Twitter’s icon shows up after it redirects to the to callback url. I intend to work on that issues soon as well as optimizing the method. Comments and suggestions are highly welcome!

First, Register your web app with Twitter and set there the callback url of your app. That’s the url the user is redirected to after authorization. Once you’ve registered your app, you’ll be provided with a consumer key and consumer secret that is unique to your app.

The code:

In a first servlet, You need to print the the authorization url so the user can click on it and he/she can authorize your web app to be able to access your Twitter account.

Get a request token

Twitter twitter = new Twitter();
twitter.setOAuthConsumer("consumerkey", "consumersecret");
RequestToken twitterRequestToken
                 = twitter.getOAuthRequestToken();

Get the token and tokenSecret and then find a way to persist them.

String token = twitterRequestToken.getToken();
String tokenSecret = twitterRequestToken.getTokenSecret();
persist(token,tokenSecret);

Print the authorization url in a jsp. I am using Spring’s abstract controller in my app and my model is a hashtable since I am printing so many things. This part is also up to you.

String authorizationUrl = twitterRequestToken.
                              getAuthorizationURL();
pageProperties.put("twitterAuthUrl",authorizationURL);

When the user sees the link and clicks on it, he/she is directed to Twitter and it asks for his/her authorization. After this the user is directed to the callback url. This is usually a second servlet but in my app it’s just another Spring abstract controller.

In a second servlet, retrieve the token and tokenSecret you persisted in the first servlet. Once that is done, get an access token

Twitter twitter = new Twitter();
twitter.setOAuthConsumer("consumerkey", "consumersecret");

AccessToken accessToken =
    twitter.getOAuthAccessToken(token, tokenSecret);
twitter.setOAuthAccessToken(accessToken);

Again, persist the token and tokenSecret that comes with the accessToken for later use.

persist(
          accessToken.getToken(),
          accessToken.getTokenSecret()
         );

Once that’s out of the way, use the Twitter
instantiations many service methods to be able to access a user’s
account.

int id = accessToken.getUserId();
User user = twitter.showUser(id+"");
String screenName = user.getScreenName();

So there you go, a quick and dirty Twitter4j Oauth for web apps.

About these ads
Tagged with: , , , ,

30 Responses

Subscribe to comments with RSS.

  1. [...] Quick and Dirty Twitter4j OAuth for Web Apps [...]

  2. [...] Comment! This is a refactored version of my post, Quick and Dirty Oauth for Twitter4J OAuth for Web Apps [...]

  3. [...] my Software Engineering problem Like I did with my Twitter4J solution. I stored the token and tokenSecret to session and used it at the callback to get an access [...]

  4. Bilal Ahmed said, on December 3, 2009 at 4:47 am

    Hello:

    I have been struggling with debugging oauth for quite a few hours now. I have gone through your blog several times with no luck. It’s something really small I am missing
    and any help would be greatly appreciated. Here is my code.

    On my jsp page, when the user clicks on ‘Sign in with Twitter’ button, I do the following:
    Twitter twitterObj = new Twitter()
    twitterObj.setOAuthConsumer(consumerKey, consumerSecret)
    RequestToken twitterRequestToken = twitterObj.getOAuthRequestToken()
    session.token = twitterRequestToken.getToken()
    session.tokenSecret = twitterRequestToken.getTokenSecret()
    redirect(twitterRequestToken.getAuthorizationURL())

    The user is sent over the Twitter where they either type in username/password, or simply hit Allow. After hitting allow, my callback URL is getting called.

    Twitter twitterObj = new Twitter()
    twitterObj.setOAuthConsumer(consumerKey, consumerSecret)
    AccessToken accessToken = twitterObj.getOAuthAccessToken
    (session.token, session.tokenSecret)
    twitterObj.setAccessToken(accessToken)

    I get the following exception:
    twitter4j.TwitterException: The user has not given access to the account.
    at twitter4j.http.HttpClient.getOAuthAccessToken
    (HttpClient.java:222)
    at twitter4j.Twitter.getOAuthAccessToken(Twitter.java:181)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke
    (NativeMethodAccessorImpl.java:39)

    Caused by: twitter4j.TwitterException: 401:Authentication credentials were missing or incorrect.

    at twitter4j.http.HttpClient.httpRequest(HttpClient.java:477)
    at twitter4j.http.HttpClient.getOAuthAccessToken
    (HttpClient.java:220)
    … 83 more

    Thanks in advance,
    Bilal

    • Jose Asuncion said, on December 3, 2009 at 3:35 pm

      Could you tell us what line your code is causing this error?

      • Bilal Ahmed said, on December 3, 2009 at 4:15 pm

        Hi Jose,

        The exception is happening on this line,

        AccessToken accessToken = twitterObj.getOAuthAccessToken(session.token, session.tokenSecret)

        when I get the callback, and my method tries to retrieve the access token. I am printing token string and token secret correctly, so I know the values are there.

        Thanks,
        Bilal

    • Andres Ruiz 35461 said, on February 17, 2011 at 3:19 am

      Hi Jeune
      I read your article that is so helpful, but i dont kow if you have to help me with a problem on my web project
      the fact is this:
      under the “/faces/*” folder the server retrive only the files that are under the root path.
      For example if i have /hola.xhtml if i ask:
      http://bla/webapp/faces/hola.xhtml (and that file doesn’t exist under /faces/)
      it get me the file in the root.
      Moreover, i ca recursly ask http://bla/webapp/faces/faces/faces/hola.xhtml, it get me
      in anycase /hola.xhtml.
      I tried everything with just a new webapplication in netbeans and gf3, i really can’t understand why it has this behviour.
      Could anyone help me? I tried to find some answers around the forum, i searched on JSF 2 specification some answer, but really can’t find the problem.
      so in a few words, if i click on a link we can see “/faces/” so if i go to other site and then return the page that has the same link that i cliked we will se “/faces/faces/”, so glassfish tell me that is not found, why
      i hope that you can help me
      thanks

      • Jose Asuncion said, on February 18, 2011 at 2:54 pm

        Hi Andres!

        Thanks for dropping by. I didn’t use JSF in my examples. Just plain ‘ol Servlets. Sorry if I can’t help you with that. Goodluck :)

        About your problem with URLs, try to find out why another “faces/” is being appended to the url. Are you sure that that you are clicking on the same link in another page?

  5. Jose Asuncion said, on December 3, 2009 at 6:10 pm

    Hmmmmm, if what you’re saying is true then I don’t know actually. I’ll try to do oauth again on my end, and then deploy the app on the net. Will get back to you. Hold on. :D

    • Bilal Ahmed said, on December 3, 2009 at 8:47 pm

      Thanks a bunch Jose :) On the side note, I am dropping a cookie for the username once authenticated. Next time user tries to authenticate I will look up oauth token and secret in the database. One issue I saw was since twitter doesn’t expire the oauth token, it’s the application provider’s responsibility to expire it periodically. This way, the token doesn’t get abused. I would love to hear any insights you have regarding that.

      Cheers!
      Bilal

  6. Savio said, on December 24, 2009 at 6:30 pm

    Hi Jose!

    Thank you for the information! I found it helpful. But I’m currently stuck somewhere – I don’t know what to do with the persisted access token and token secret. how do i use it such that my application has permanent authentication to twitter without having to always grant permission from the user’s end?

    Thanks a lot!

    Regards,
    Savio

    • Jose Asuncion said, on December 24, 2009 at 6:36 pm

      Hi Savio, you have to store/persist the token and token secret to some kind of database like MySQL or in my case I am using AppEngine DataStore.

      Then you can retrieve them again without having to always grant permission from the user’s end.

      Twitter twitter = new Twitter();
      twitter.setOAuthConsumer(“consumerkey”, “consumersecret”);

      AccessToken accessToken =
      twitter.getOAuthAccessToken(token, tokenSecret);
      twitter.setOAuthAccessToken(accessToken);

  7. Savio said, on December 24, 2009 at 6:31 pm

    i would like to know if you have a solution!

  8. Savio said, on December 24, 2009 at 7:11 pm

    Hi Jose!

    Thanks a lot for your work! it really help. I figured what method to call to use the access token and the access token secret.

    twitter.setOAuthAccessToken(dataStore.getAccessToken() , dataStore.getAccessTokenSecret() );

    thanks a lot for your work!

    Savio

  9. Bilal Ahmed said, on December 30, 2009 at 5:12 am

    Hi Jose,

    I found out the problem. This article helped a lot, showing code from grails.

    http://blogs.bytecode.com.au/glen/2009/12/08/log-into-your-grails-app-using-your-twitter-credentials.html

    The solution is that you should keep the twitter object and request token object in the session. When the call back happens, use the same session object to pull out access token. Also, use the request token to generate the auth URL.

    Cheers,
    Bilal

    • Jose Asuncion said, on December 31, 2009 at 6:49 pm

      Hi Bilal, good to see you solved your problem! Hope my blogpost was able to help you somehow. Happy new year!

  10. Bilal Ahmed said, on December 31, 2009 at 7:16 pm

    Your blogpost is awesome Jose and that really got me started :)

    Hope you are having great holidays and happy new year.

    Bilal

  11. Itzik yatom said, on February 8, 2010 at 8:43 am

    Ho Jose,

    Thank you for your post. I have just used it to start my new Twitter project with Twitter4J.

    I have found a small bug in your last code snippet : Need to pass the id as an int not as a String. The String argument matches the signature of a similar method that requests user by his screen name not his ID.

    Thanks
    Itzik

    • Jose Asuncion said, on February 8, 2010 at 7:39 pm

      Hi there! It’s been since I last checked if the code I have here is correct. The version of Twitter4J I was using back then was Twitter4J 2.0.9 and I haven’t been using it since then. Maybe the something changed in the library. Thanks for mentioning it anyway. Goodluck on your project! :D

  12. Tiago said, on March 3, 2010 at 7:30 pm

    Man i got this to work until

    this…
    int id = accessToken.getUserId();

    here throwns an exception
    User user = twitter.showUser(id+””);
    String screenName = user.getScreenName();

    the accessToken was throwing an exception as well had to change to…
    RequestToken requestToken = (RequestToken) request.getSession().getAttribute(“requestToken”);
    String oauthVerifier = request.getParameter(“oauth_verifier”);
    AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, oauthVerifier);
    twitter.setOAuthAccessToken(accessToken);

    instead of calling
    AccessToken accessToken = twitter.getOAuthAccessToken(token, tokenSecret); twitter.setOAuthAccessToken(accessToken);

    Anyway now i got it workign until the ID bit
    i’d like to know how could i use the…
    twitter.updateStatus(“text”); then

    i’m getting all the values

    TOKEN hfUtadgxmBn2w5eBAXnRZjA7YumDbR563SGkv4i3M5E
    TOKEN SECRET d6QsSqx9fJKqsYJXtBD6nOx4fAiOS6VelKRmdj6VM
    ACCESS TOKEN 116447190-mbArGZrB2U8g8sFu9nnZlwCyjQYAr3B7p0MtDT84
    ACCESS TOKEN SECRET 4fBtlopBGBUKqldIDngm9MD2sripcgCELwvPtxRYdc
    ID 116447190

    now i wanted to use the methods for the logged user.

    Thanks a lot.

    • Jose Asuncion said, on March 4, 2010 at 1:32 am

      Hi Tiago,

      I wrote the code in the blog post last year. Back then it was still Twitter4J 2.0.10. Twitter4J has gone through a lot of changes since then and maybe the methods right now are deprecated I don’t know. It’s been a while since I worked with Twitter4J. But I see that you have made it work and Congratulations! Hats off to you :D

      As for how to use twitter.updateStatus(“text”); — I think there’s nothing wrong with what you’re doing assuming you have set the Twitter instantiation correctly e.g the consumer key and consumer secret are correct, the token and tokenSecret associated with the user are correct.

  13. Tiago said, on March 3, 2010 at 7:57 pm

    twitter.createFriendship(screenName);

    16:55:04,984 ERROR [[twittercallback]] Servlet.service() for servlet twittercallback threw exception
    twitter4j.TwitterException: 401:Authentication credentials were missing or incorrect.
    {“request”:”/1/friendships/create.json?screen_name=userName”,”error”:”Read-only application cannot POST”}

    What does that mean? thanks

  14. Venkata said, on March 18, 2010 at 6:57 am

    Hi,

    This artical really help me to do start of webapplication.

    can someone suggest me how to do logout?

    When ever i log out from my webapp it has logout from the twitter also.
    Is that possible to do the same?

    Thanks
    Venkata

    • Jose Asuncion said, on March 18, 2010 at 1:53 pm

      Hi, with OAuth you don’t need to login/logout. All you need to do if you want to access your Twitter account is to get the token and tokenSecret and access on demand.

  15. Tiago said, on March 18, 2010 at 4:53 pm

    Hi guys,

    found what was happening…

    had to ajust the clock… the guy responsible for the server just run an line to update the time and its working now.

    there we go…
    http://blainegarrett.com/2009/07/14/failed-to-validate-oauth-signature-and-token-on-twitter-oauth-check-your-cloc/

    Thanks for all.

  16. venkatareddy.pammi said, on June 18, 2010 at 2:55 pm

    Hi,

    I have integrated Twitter4j login functionality for my proceject
    successfully.

    Step.1) if i click on twitter button takes me to twitter login pop up
    box with “Allow” and “Deny” buttons

    Step.2) if i enter proper twitter username and password, it is
    redirecting me to the twitter call back url which is to my application
    url.

    Upto this everything is working fine.

    Step.3) After (Step.1), if i click on “Deny” button it is redirecting
    to the twitter popup box with some information(OK, you’ve denied
    localvc access to interact with your account! Feel free to find other
    applications and find out what people are talking about right now at
    Twitter.).

    Then closed the twitter popup box, if i comes back to my app login
    page it is giving me exception “Stack Overflow”.

    If i close the browser, reopen the new browser and then i could able
    to access the my app login page without any problem.

    How can i resolve the ‘Stack overflow exception’ issue after clicking
    “Deny” button?
    Is there any functionality to take care on “Deny” button?

    StackOverflow exception:

    Caused by: javax.servlet.ServletException:
    java.lang.StackOverflowError
    at
    org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:
    855)
    at
    org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:
    784)
    at org.apache.jsp.jsp.user.login_jsp._jspService(login_jsp.java:362)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:
    384)
    at
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:
    320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:
    290)
    at
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:
    206)
    at
    org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:
    687)
    at
    org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:
    590)
    at
    org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:
    505)
    at
    org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:
    968)
    at
    org.apache.jasper.runtime.PageContextImpl.doInclude(PageContextImpl.java:
    643)
    at
    org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:
    637)
    at
    org.apache.tiles.jsp.context.JspTilesRequestContext.include(JspTilesRequestContext.java:
    80)
    … 93 more
    Caused by: java.lang.StackOverflowError
    at twitter4j.http.OAuthAuthorization.hashCode(OAuthAuthorization.java:
    445)
    at twitter4j.http.RequestToken.hashCode(RequestToken.java:95)
    at twitter4j.http.OAuthAuthorization.hashCode(OAuthAuthorization.java:
    447)
    at twitter4j.http.RequestToken.hashCode(RequestToken.java:95)
    at twitter4j.http.OAuthAuthorization.hashCode(OAuthAuthorization.java:
    447)
    at twitter4j.http.RequestToken.hashCode(RequestToken.java:95)
    at twitter4j.http.OAuthAuthorization.hashCode(OAuthAuthorization.java:
    447)
    at twitter4j.http.RequestToken.hashCode(RequestToken.java:95)
    at twitter4j.http.OAuthAuthorization.hashCode(OAuthAuthorization.java:
    447)
    at twitter4j.http.RequestToken.hashCode(RequestToken.java:95)
    at twitter4j.http.OAuthAuthorization.hashCode(OAuthAuthorization.java:
    447)

    • Jose Asuncion said, on June 21, 2010 at 5:19 pm

      venkatareddy.pammi, that’s funny I have never really tried clicking the “Deny Button”. I suggest you ask Yusuke directly at the Twitter4J forums. Cheers. :D

  17. Harshit said, on September 17, 2011 at 12:37 am

    i created an simple tutorial for twitter authentication Twitter Auth using java and spring

  18. dips said, on October 8, 2011 at 12:37 pm

    I have created a twitter App in Android, I want signout functionality in my app, I remove the stored AccessToken in the preference file, but when I am showing Authorization page click on the signout button its showing 10-08 18:02:02.127: WARN/System.err(959): twitter4j.TwitterException: 401:Authentication credentials were missing or incorrect.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: