So, a few weeks ago Twitter replaced Basic Auth for OAuth in their APIs. I was aware of this of course, but it never occurred to me to worry about it as I don't actually work on a Twitter client myself. However, I forgot that one of my sites, CFBloggers.org, makes use of the Twitter API to tweet new blog entries it aggregates. When I tweeted about this today I got a lot of recommendations, but for the most part, the advice, and the docs, focused on applications for humans. By that I mean, the assumption was that your Twitter automation was a tool that random users were using. The docs would explain how you could easily direct them to Twitter to authorize your application and how they would be sent back. That's great, but what about the case for Twitter bots? Nothing out there seemed to address that need. Luckily though I got some great help. In this blog post I'll explain exactly how I updated CFBloggers to post to Twitter. While this is a ColdFusion specific post it really could apply to anyone doing Twitter bots. Credit for this goes to Todd Rafferty, Vic Carter, and Rob O'Brien (and specifically his blog post here: Integrating Twitter and OAuth with ColdFusion)

Ok, so before I get into the exact steps, let me summarize what we are going to do here. We are going to switch to a Java based Twitter library that makes use of OAuth-wrapped calls to Twitter. That handles the sending of tweets. To handle "allow my web site to do this" we are going to use a temporary script. The temporary script is a one time process that we will use to get our tokens that are then fed to the Twitter client. Once we have that we should be gold.

Edited September 16: Reader Angela Haralson pointed out (see comments below) a great time saver. The creation of the temporary script to get AccessToken and Secret is not necessary. You can get those values from the Twitter web site. This makes things even easier! Please keep that in mind when reading below. Basically you can focus more on the Java library and your setup at Twitter.com.

  1. The first step is to get the Java library. At this time there are no ColdFusion Twitter clients that make use of OAuth, but if anyone knows of one, or creates one after this entry is released, please post it below. The Java library is called Twitter4J and may be found here: http://twitter4j.org/en/index.html

  1. You can put the Twitter4J jar in your ColdFusion class path, or do it the sexy way and make use of JavaLoader. I made use of JavaLoader. This is what I added to my Application.cfc:

<cfset var paths = [expandPath("./components/twitter4j-core-2.1.4-SNAPSHOT.jar")]> <cfset application.javaloader = createObject("component", "components.javaloader.JavaLoader").init(paths)>

<cfset application.Twitter = application.javaloader.create("twitter4j.Twitter")>

  1. This is the beginning of the one time process! We need to create an application on the Twitter web site. This is the application that represents our web site robot. Go to http://dev.twitter.com and login. You can login as your primary Twitter account or the robot's account. In the top nav click "Your Apps" and select Register a New app.

  1. The application name, description, and web site are not important. However, the application name is what folks will see when you robot tweets. I picked "CFBloggersRobot" for mine. For the application web site I just used CFBloggers.org. For the organization I said Me. It's a great organization but the benefits suck. Now for two critical parts. Application Type must be Browser. The call back URL is going to be a temporary script we will make in the next step. Notice that the call back URL can be a local url, by that I mean I used dev.coldfusionbloggers.org, which is only recognized by my local machine. I used this url: http://dev.coldfusionbloggers.org/ray.cfm?mode=1. The mode=1 is also critical and will make sense one you see the script. Finally, ensure you set access type to Read and Write. Otherwise you will not be able to send tweets.

  1. After you save the application you will go to a settings page. Notice that there are two values here you will need, the consumer key and the consumer secret. This will be used in step 6.

  1. Ok, now we are going to create the temporary script:

<cfset Twitter = application.javaloader.create("twitter4j.Twitter")> <cfset Twitter.setOAuthConsumer('cosumer key','consumer secret')>

<cfif structKeyExists(url,'mode') IS FALSE>

<!--- // 2. Authorize ---> <cfset RequestToken = Twitter.getOAuthRequestToken()> <cfset Session.oAuthRequestToken = RequestToken.getToken()> <cfset Session.oAuthRequestTokenSecret = RequestToken.getTokenSecret()> <cflocation url="#RequestToken.getAuthorizationURL()#" addtoken="No">

<cfelse>

<!--- // 3. Authenticate // ---> <cfset AccessToken = Twitter.getOAuthAccessToken(Session.oAuthRequestToken,Session.oAuthRequestTokenSecret)> <cfset session.StoredAccessToken = AccessToken.getToken()> <cfset session.StoredAccessSecret = AccessToken.getTokenSecret()> <cfdump var="#session#"><cfabort>

</cfif>

So the script begins by getting an instance of the Twitter Java library. I have this in Application scope already but as this is a one time script I wanted to keep it simple. Notice the two strings. Replace those with the real value. Now open this baby up in your browser - and to be clear, you can do this all locally just fine.

When you run this you will get sent to the Twitter authorization page. Obviously you want to allow your application. Twitter will then send you right back to the script with mode=1 in the URL. This will trigger the dump you see. Within that dump you want to grab the values for storedaccesstoken and storedaccesssecret.

  1. Return back to your application.cfc. You need to provide all 4 values to your Twitter object:

<cfset var paths = [expandPath("./components/twitter4j-core-2.1.4-SNAPSHOT.jar")]> <cfset application.javaloader = createObject("component", "components.javaloader.JavaLoader").init(paths)>

<cfset application.Twitter = application.javaloader.create("twitter4j.Twitter")> <cfset application.Twitter.setOAuthConsumer('consumerkey',consumersecret')> <cfset application.Twitter.setOAuthAccessToken("storedaccesstoken" ,"storedaccesssecret")>

  1. The final step is to update your code from the old way of sending Tweets to the new way. Luckily this is very trivial. I changed:

<cfset twit_result = application.twitter.statuses_update(message)>

to

<cfset application.twitter.updateStatus(message)>

And that's it. Once things were explained to me the actual coding took approximately 5 minutes.