Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I access auth-only Twitter API methods from a web application

I have a web application for iPhone, which will ultimately run within a PhoneGap application - but for now I'm running it in Safari.

The application needs to access tweets from Twitter friends, including private tweets. So I've implemented OAuth using the Scribe library. I successfully bounce users to Twitter, have them authenticate, then bounce back.

At this point the web app has oAuth credentials (key and token) which it persists locally. From here on I'd like it to user the Twitter statuses/user_timeline.json method to grab tweets for a particular user. I have the application using JSONP requests to do this with unprotected tweets successfully; when it accesses the timeline of a private Twitter feed, an HTTP basic authentication dialog appears in the app.

I believe that I need to provide the OAuth credentials to Twitter, so that my web application can identify and authenticate itself. Twitter recommends doing so through the addition of an HTTP Authorization header, but as I'm using JSONP for the request I don't think this is an option for me. Am I right in assuming this?

My options therefore appear to either be putting the oAuth credentials as query-string parameters (which Twitter recommends against, but documentation suggests still supports); or proxying all the Tweets through an intermediate server. I'd rather avoid the latter.

I access the Twitter API using URLs of the form

http://api.twitter.com/1/statuses/user_timeline.json?user_id=29191439&oauth_nonce=XXXXXXXXXXX&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1272323042&oauth_consumer_key=XXXXXXXXXX&oauth_signature=XXXXXXXXXX&oauth_version=1.0

When user_id is a public user, this works fine. When user_id is a private user, I get that HTTP Basic Auth dialog. Any idea what I'm doing wrong? I'm hoping it's something embarrassingly simple like "forgetting an important parameter"...

like image 440
Tom Hume Avatar asked Jan 20 '11 20:01

Tom Hume


1 Answers

The oAuth stanza needs to be exact, as per http://dev.twitter.com/pages/auth#auth-request - I ended up building an Authorization: header that I could first check with curl.

I built it using the really helpful interactive request checker at http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/

Here's a friends API request for a protected user:

curl -v -H 'Authorization: OAuth realm="https://api.twitter.com/1/friends/ids.json", oauth_consumer_key="XXXXXXXXXXXXXXXX", oauth_token="XXXXXXXXXXXXXXXX", oauth_nonce="XXXXXXXXXXXXXXXX", oauth_timestamp="1300728665", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="XXXXXXXXXXXXXXXX%3D"' https://api.twitter.com/1/friends/ids.json?user_id=254723679

It's worth re-iterating that as you've tried to do, instead of setting the Authorization header via e.g. jquery's beforeSend function, that for cross-domain JSONP requests (which can't add HTTP headers) you can make oAuth requests by putting all the relevant key/value pairs in the GET request. This should hopefully help out various other questioners, e.g

  1. Set Headers with jQuery.ajax and JSONP?
  2. Modify HTTP Headers for a JSONP request
  3. Using only JQuery to update Twitter (OAuth)

Your request looks like it has a couple of problems; it's missing the user's oauth_token plus the oauth_signature doesn't look like it has been base64 encoded (because it's missing a hex encoded = or ==, %3 or %3D%3D respectively).

Here's my GET equivalent using oAuth encoded querystring params, which you can use in a cross-domain JSONP call:

https://api.twitter.com/1/friends/ids.json?user_id=254723679&realm=https://api.twitter.com/1/friends/ids.json&oauth_consumer_key=XXXXXXXXXXXXXXXX&oauth_token=XXXXXXXXXXXXXXXX&oauth_nonce=XXXXXXXXXXXXXXXX&oauth_timestamp=1300728665&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=XXXXXXXXXXXXXXXX%3D
like image 78
jaygooby Avatar answered Oct 03 '22 09:10

jaygooby