worrbase

Google App Engine, Twitter4J and OAuth

2010-03-13

So I'm writing a Twitter app in Java on Google App Engine right now with my friend, Dave Bright. We're using Google Web Toolkit for our frontend, and App Engine for hosting and database and such. Twitter4J is our Twitter library of choice.

Since we ran into a spot of trouble using OAuth with the Twitter4J library, I decided to give a bit of a brief tutorial on how to get it working on App Engine. There is actually very different than the code in my as I do some more error checking, and need to do some other stuff with my datastore.

Twitter4J OAuth Overview

  1. Set the consumer key and secret for your twitter object with setOAuthConsumer(key, secret)
  2. Get a request token with getRequestToken(callback_uri)
  3. Persist the request token somewhere, we'll need the original later when we need to get the access token.
  4. Redirect the user to the URL returned by getAuthorizationURL()
  5. Get the persisted request token, setOAuthConsumer again.
  6. Call getOAuthAccessToken(request_token, oauth_verifier) to get an access token
  7. Persist that token with the user data, you'll need this everytime you want to authenticate.

Some incomplete example code

Please note, this is not code I actually have in production anywhere. It's original code just for the blog.
public String authenticate() {
    TwitterFactory tf = new TwitterFactory();
    Twitter twitter = tf.getInstance();

    // This is actually really important, as Twitter WILL NOT send you back the oauth_verifier if
    // you don't provide the callback URI, even if you provide a callback on their site
    twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
    RequestToken rtoken = new RequestToken(CALLBACK_URI);

    // This is a special class that just relates the token to the RequestToken object in the app engine
    // datastore. The token string itself is the key.
    OAuthTemp temp = new OAuthTemp(rtoken.getToken(), rtoken);

    // Our persistence manager is named pm
    pm.makePersistent(temp);

    return rtoken.getAuthorizationURL();
}

The second bit of the code gets called when the user is returned to the page. You need to get the oauth_token and the oauth_verifier GET variables and pass them to this function.

public void authenticatePartII(String oauth_token, String oauth_verifier) {
    TwitterFactory tf = new TwitterFactory();
    Twitter twitter = tf.getInstance();

    // Get the temp object out of the datastore, and get the old RequestToken
    // Yes, it MUST be the old RequestToken. Or at least, have all the same parameters
    // as the old RequestToken.
    Key k = KeyFactory.createKey(OAuthTemp.class.getSimpleName(), oauth_token);
    OAuthTemp temp = pm.getObjectById(OAuthTemp.class, k);
    RequestToken rtoken = temp.getrtoken();

    // You MUST provide the original RequestToken and the oauth_verifier passed to you by Twitter
    twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
    AccessToken ac  = twitter.getOAuthAccessToken(rtoken, oauth_verifier);

    // You really don't need the RequestToken information after you got your AccessToken, so
    // delete it.
    twitter.setOAuthAccessToken(ac);
    pm.deletePersistent(temp);

    // However you store user data, you ought to associate the AcessToken object you
    // just got with your twitter user, and pop it in the datastore. I'll leave that bit up to you.
}

That's all there really is to it. The Twitter4J library isn't the best documented library, and just looking at the Javadocs and the Desktop-centric code examples isn't really that helpful. I hope this clears up some confusion on how to get Twitter4J working with OAuth.