on 22nd August 2010 at 23:56
Simple shell scripting for Twitter
I have a few scripts which manage my URL log, including posting a copy of the feed to my Twitter and del.icio.us accounts. Until recently the scripts have just used wget's HTTP Basic Auth support to authenticate to my accounts. This has to change because Twitter is switching to oauth. This switch has already been delayed but is now due to occur by the end of August.
Most oauth implementations are not designed for old school languages like the Unix shell, so I procrastinated because I didn't fancy dealing with the dependency hell of mainstream scripting languages. But I perked up when I noticed Jef Poskanzer mentioning his stand-alone oauth implementation on his twitter feed. I have liked Jef's approach to writing simple code since I worked on thttpd in support of Demon's homepages service.
Posting to Twitter with basic auth didn't require anything beyond a Twitter account. You could just POST to https://twitter.com/statuses/update.json - which is the essence of the security problem that the Twitter crew want to solve.
To use oauth you must register an application. Go to https://dev.twitter.com/ -> Get started -> Your apps -> Register a new app. Fill in the form. Tell it the app is a client app and give it read+write permission.
When you have done that you will be presented with your application's settings page. The interesting parts are the "consumer key" and the "consumer secret" which are the half of your app's oauth credentials which authenticate the application to Twitter. The other half of the credentials prove that your app may do something to a particular person's Twitter account. In order to obtain the second half oauth normally requires a fairly complicated dance. Happily, for simple cases where you want to script your own account, Twitter provides a shortcut.
On your application's settings page, click the "My Access Token" link. This gives you a page containing your "access token" and "access token secret" which together with your "consumer key" and "consumer secret" allow your app to post to your Twitter account.
Now you need some software. Fetch Jef Poskanzer's oauth_sign and http_post packages. You can use oauth_sign with wget or curl, but http_post is more convenient since both it and oauth_sign encode the query parameters for you, whereas wget and curl do not. Typing make should be enough to build oauth_sign; for http_post you probably want make SSL_DEFS="-DUSE_SSL" SSL_LIBS="-lssl -lcrypto".
Now you have everything you need to write a simple shell twitter client. Something like:
#!/bin/sh consumer_key="COPY-FROM-APP-SETTINGS-PAGE" consumer_secret="COPY-FROM-APP-SETTINGS-PAGE" access_token="COPY-FROM-MY-ACCESS-TOKEN-PAGE" access_secret="COPY-FROM-MY-ACCESS-TOKEN-PAGE" url="https://api.twitter.com/1.1/statuses/update.json" http_post -h Authorization "$(oauth_sign \ $consumer_key $consumer_secret \ $access_token $access_secret \ POST "$url" status="$*")" \ "$url" status="$*"
That should be enough to get you going.
For completeness (and since I worked out how to do it I'm going to inflict it on you) here's how to use Jef's tools to do the full three party oauth procedure.
- First obtain a request oauth token and secret. For this transaction your oauth token and secret are empty. The HTTP request is a POST with an empty body.
http_post -h Authorization "$(oauth_sign \ $consumer_key $consumer_secret "" "" \ POST https://api.twitter.com/oauth/request_token)" \ https://api.twitter.com/oauth/request_token
- The response will contain oauth_token and oauth_token_secret parameters which are your request token and secret. You must then get your victim to visit the URL https://api.twitter.com/oauth/authorize?o
auth_token=$request_token. They will be asked to give your app permission to diddle with their account. (They may have to log in first.)
- When they have done this they will be redirected to your app's callback URL, with some extra parameters. The documentation says these will be a copy of the request oauth_token and an oauth_verifier but in my testing the verifier was missing.
- If your app is a client app (which has no callback URL or the URL is "oob") then the user will be presented with a PIN which is the request verifier.
- You can now obtain the access token and secret as follows.
http_post -h Authorization "$(oauth_sign \ $consumer_key $consumer_secret \ $request_token $request_secret \ POST https://api.twitter.com/oauth/access_token oauth_verifier="$verifier")" \ https://api.twitter.com/oauth/access_token oauth_verifier="$verifier"
- The response will contain oauth_token and oauth_token_secret parameters which are the access token and secret that you must use when your app wants to do something with your victim's account.
I hope this might be of use to someone else...