OAuthcalypse Now: Tweeting with Twitter, OAuth and Django

The Twitter OAuthcalypse hit me last week. Back in July, I used Twitter’s basic authentication scheme in a new site I’m working on (wantbox.com) to easily send out tweets via my @wantbox account whenever someone posted a new “want” to the site.

This integration took about 30 minutes to research and implement. All I had to do was put my twitter username and password in my Django project’s settings.py file, pip install the python-twitter app into my virtualenv and then use:

from django.conf import settings
import twitter
api = twitter.Api(username=settings.TWITTER_USERNAME, password=settings.TWITTER_PASSWORD)
api.PostUpdate('Someone in 02481 wants "a home gym" %s' % extra_stuff)

The resulting tweet would appear in my @wantbox stream appearing to come “via API”. Easy-peasy.

Last week, however, I started getting “401 Unauthorized” errors whenever I tried to post to Twitter. Clearly the Twitter API team had officially turned off basic authentication and was now requiring all apps to connect using OAuth.

Yesterday around lunchtime I stopped work on the fun new wantbox feature I was working on so I could “quickly fix” my broken Twitter posting. Oh boy…quickly and OAuth clearly don’t play well together. I tried a bunch of solutions which ultimately failed. I worked through the night…I got up in the morning and worked some more. I gave up. I stubbornly came back. I gave up again. I lost hope:

Finally, when all hope was nearly loss, I succeeded in connecting to my Twitter account via OAuth and posting a tweet!

I completely understand the rationale for moving to OAuth (no more Twitter passwords stored on third-party sites, easier management of who can connect, etc…) but the process of getting there was painful to me. If by sharing my experience I save even one of you from some of this pain, then my job is done.

How I eventually got it working

I was fortunate to find Jeff Miller’s blog post “Twitter from the command line in Python using OAuth.” It was the resource that got me over the top (thanks Jeff!) Keep in mind that my goal was connecting one Twitter account (@wantbox) to the Twitter app I created (wantbox.com). I am not yet adding the feature of letting individual site users connect their Twitter accounts to my Twitter app.

STEP ONE: Connecting your Twitter Account to your Twitter App

  1. Log into the Twitter account where you want to create a Twitter App
  2. Create the Twitter app: http://twitter.com/apps/new
    1. application name: this will be in the from line e.g. “via wantbox.com”
    2. application type: client
    3. access type: read & write
    4. make a note of your “Consumer key” and “Consumer secret”
  3. Activate your virtualenv if you are using virtualenv
  4. pip install tweepy
  5. pip install simplejson
  6. Open a python shell
  7. >>> import tweepy
  8. >>> auth = tweepy.OAuthHandler(‘PASTE YOUR CONSUMER KEY’, ‘PASTE YOUR CONSUMER SECRET’)
  9. >>> auth_url = auth.get_authorization_url()
  10. >>> print ‘Please authorize: ‘ + auth_url
  11. Keep your python shell open, and copy and paste the returned URL into a browser. You should see a Twitter page indicating that “An application would like to connect to your account”. Make sure you are logged into the Twitter account that you want to connect and then click the “Allow” button.
  12. Since you setup your app as a client, Twitter will return to you a PIN. Make a note of it and go back to your open python shell
  13. >>> auth.get_access_token(PASTE_YOUR_PIN)
  14. >>> print “ACCESS_KEY = ‘%s'” % auth.access_token.key
  15. Make a note of this ACCESS_KEY
  16. >>> print “ACCESS_SECRET = ‘%s'” % auth.access_token.secret
  17. Make a note of this ACCESS_SECRET

STEP TWO: Sending a Tweet via your Twitter Account/App

  1. Open a new python shell
  2. >>> import tweepy
  3. >>> auth = tweepy.OAuthHandler(‘PASTE_CONSUMER_KEY’, ‘PASTE_CONSUMER_SECRET’)
  4. >>> auth.set_access_token(‘PASTE_ACCESS_KEY’, ‘PASTE_ACCESS_SECRET’)
  5. >>> api = tweepy.API(auth)
  6. >>> api.update_status(“Hello, brave new Twitter/OAuth world!”)

If all goes well, you’ll see something like “<tweepy.models.Status object at 0x6c91aafb8a90>” in your command line and the following in your Twitter stream:

You can now tuck the above code (steps 2-6) into a python function and tweet at will.

The gotcha that gotme for 24+ hrs

Try your test tweeting from a public, outside-the-home-firewall server. I kept getting “401 Unauthorized” errors when I tried connecting to Twitter from my home dev server, but was successful on my first try when I tried on my public, wantbox.com server. I suspect that the failed earlier solutions (python-twitter, oauth-python-twitter, twitter_app, etc…) would have worked if I tried them on a live server. I don’t know why I can’t get authenticated from home, but I’m happy it works in the wild.

There you have it. The process took a couple years off my life, but I’m a better man because of it. If you have any questions, ask them in the comments. If I encountered and solved your particular problem I will respond. If I haven’t I will leave it to the community to do so.

I love the smell of tweeting in the morning.