This is the first post in what will most likely be a series of posts related to Twitter, POP3, SMTP and Twisted. This post will be about asynchronous authentication with Twitter using xAuth.
xAuth is a simplified form of OAuth. Instead of doing the dance, you use credentials(like basic auth), but exchange them for an access token. You need to send a request to api@twitter.com to enable it.
This technique is also applicable to getting OAuth tokens, although that is more complicated.
We are going to use Twitty Twister, which is a Twitter lib for Twisted which supports signing OAuth requests. It does not, however, include code for obtaining an access token.
To obtain the token, it is suggested to use an external library. But since my app is 100% Twisted, and most OAuth libs blocking, I had a problem right there. We don’t want to have our nice reactor sit idle while we request our token, do we?
The solution is to use python-oauth to make the request, but just before we send it, you call request.to_postdata() and use twisted.web.client.getPage to send the request in an asynchronous manner.
My main resources where: http://dev.twitter.com/pages/xauth http://github.com/simplegeo/python-oauth2#readme http://twistedmatrix.com/documents/10.1.0/api/twisted.web.client.getPage.html
The resulting code(insert your key, secret, username and password):
from oauth import oauth from twisted.web.client import getPage from twisted.internet import reactor from twittytwister import twitter import cgi url = "https://api.twitter.com/oauth/access_token" consumer = oauth.OAuthConsumer("key", "secret") def respond(tokens): params = cgi.parse_qs(tokens, keep_blank_values=False) key = params['oauth_token'][0] secret = params['oauth_token_secret'][0] print "got access" token = oauth.OAuthToken(key, secret) tweet = twitter.Twitter(consumer=consumer, token=token).update("Hello world! First tweet using xauth via #Twisted and #Python") tweet.addCallback(posted) def posted(message): print "message:", message request = oauth.OAuthRequest.from_consumer_and_token(oauth_consumer=consumer, http_method='POST', http_url=url, parameters = { 'x_auth_mode': 'client_auth', 'x_auth_username': 'username', 'x_auth_password': 'password' } ) request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, None) page = getPage(url, method='POST', postdata=request.to_postdata()) page.addCallback(respond) print "running..." reactor.run()