any possible way to call authorized twitter API method directly from javascript?

alfin_akhret
@alfin_akhret Alfin Akhret

Hi guys,

I am currently creating Twitter client application. It's just like Tweetdeck or something similar. The different is it's web based and using Codeigniter and Elliot Haughin Twitter Library.

I was able to do Oauth and call the twitter home_timeline, user_timeline, and mentions using serverside script. Also, i was able to display those data on the webpage and refresh it every 30 seconds using Jquery. The problem is the Twitter RESTAPI rate limitation only give a specific IP address 150 request per hour. With the 30 per second ajax call I made via Jquery, it make my server able to do 120 request to twitter API. The rest 30 requests left is not a problem if I have only one user assuming he/she is only make update status less than 30 req per hour. But, I am sure the more serious problem will occur when I have more user registered to my server.

A friend suggested me to call twitter API directly from jquery so the server side don't need to make a call. It works, but only for public method such as displaying user_timeline. When i tried to call the home_timeline or mentions, the twitter return "401 - authorized error". I understand that the call need OAuth to fulfill the request. My questions:

  1. Is there any possible way to make a call to authenticated API method directly from Javascript? if it so, how to do it? (i've searched and googling for days but can't find practical solution)
  2. If it so, do I need to include my user request token and secret token along with the call?
  3. Is it safe to include the tokens within javascript?

Please help me. I really appreciate any solution from you guys.

Best Regard

2 years 14 weeks ago

Replies

episod
@episod Taylor Singletary
  1. We don't support or recommend performing OAuth directly through Javascript -- it's insecure and puts your application at risk. The only acceptable way to perform it is if you kept all keys and secrets server-side, computed the OAuth signatures and parameters server side, then issued the request client-side from the server-generated OAuth values.
  2. The OAuth access token will need to be part of the call and the oauth_token_secret will need to be used to compute the signature
  3. No

Thanks!

2 years 14 weeks ago
JustinCM
@JustinCM Justin Moses

For #1, would an easy way to do this be to just utilize an existing twitter oauth library (e.g. for PHP) and instead of allowing it to make the request have it return the request to jquery (via an ajax call) so the client can make the request and display the response? What do you think?

2 years 12 weeks ago
episod
@episod Taylor Singletary

This is feasible as long as you don't end up creating an open proxy in the process -- only your web site should be able to interact with that layer. You may run into some trouble additionally with cookies -- if at all possible, strip them between each request and insure everything is done over SSL. But at this point, why wouldn't you just make the connections server-side?

2 years 11 weeks ago
JustinCM
@JustinCM Justin Moses

Because of rate limits (on the servers IP). Could you look at my question here: https://dev.twitter.com/discussions/5368 I am getting a 401 error when I try to use jQuery's getJSON() method with the URL that PHP generates and I am not sure why. Any ideas?

2 years 11 weeks ago
episod
@episod Taylor Singletary

But if you're doing OAuth, your rate limits are per-user and shouldn't be an issue on your server's IP address. You shouldn't have rate limiting issues when properly using OAuth. Perhaps the OAuth signatures you're generating server-side are invalid to start with?

2 years 11 weeks ago
JustinCM
@JustinCM Justin Moses

I was under the impression that some calls applied to the server IP regardless if they are logged in or not, like using the search API for instance. I want to use all the functionality of the API so I think I would not be able to do this without hitting rate limits constantly from my servers IP.

I am pretty sure they are valid because the work from the PHP side, and if I copy/paste the URL that jQuery is using into my browser window, it works just fine.

You can try it out here:
1. Authorize the app: http://tweetvision.com.php5-19.dfw1-2. websitetestlink.com/authorize
2. Makes call to "/verify_credentials" in PHP and jQuery: http://tweetvision.com.php5-19.dfw1-2.websitetestlink.com/get

2 years 11 weeks ago
episod
@episod Taylor Singletary

The REST API (api.twitter.com/1/*) accepts authentication for every method. When you use authentication, it's pulled from the user's rate limit.

The Search API, which is rate limited totally differently than the REST API, doesn't use OAuth or any form of authorization. This is where you'd likely want to use vanilla JSON-P requests.

Just because an OAuth signed request returns data, doesn't mean the request was valid OAuth. In contexts where we can consider an invalid request as an unauthenticated request instead, we'll service it.

2 years 11 weeks ago
JustinCM
@JustinCM Justin Moses

Thanks for the feedback. I will try that out. I thought the REST API had a couple methods that would hit the user rate limit AND the server rate limit but it sounds like that is not the case. Correct?

Re: OAUTH signed requests:
When I called account/verify_credentials from PHP, I got a response with my profile credentials (name, image, profile info, etc.) That means it must have been a valid request, right?

My best guess as to why I get a valid response with copy/pasting the signed URL into my browser address bar and not with jQuery is because I am calling it wrong from jQuery.

Here are the HTTP headers when copy/pasting the URL into the address bar:

https://api.twitter.com/1/account/verify_credentials.json?oauth_consumer_key=j17jEJEZhnNPxoJMIgejg&oauth_nonce=e25c9a9b76b7988ca76c13cc236810ce&oauth_signature=TMYCZjlcVz0QHpqc5DUmtWLRcdo%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1328115070&oauth_token=29741933-V7ej6I6Ip889BrNpsZI4o59VuCRiBDztkFRsybiVX&oauth_version=1.0

GET /1/account/verify_credentials.json?oauth_consumer_key=j17jEJEZhnNPxoJMIgejg&oauth_nonce=e25c9a9b76b7988ca76c13cc236810ce&oauth_signature=TMYCZjlcVz0QHpqc5DUmtWLRcdo%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1328115070&oauth_token=29741933-V7ej6I6Ip889BrNpsZI4o59VuCRiBDztkFRsybiVX&oauth_version=1.0 HTTP/1.1
Host: api.twitter.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Cookie: pid=v1%3A1327564106771214543541; k=10.34.124.113.1328070795184680; guest_id=v1%3A132807079518878852; __utma=43838368.683966938.1328070823.1328070823.1328114753.2; __utmz=43838368.1328070823.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmb=43838368.2.10.1328114753; lang=en; twid=u%3D29741933%7CCaWywqVF2Rt%2B%2FIEXdtQoA1JG6gg%3D; _twitter_sess=BAh7CToHdWEwIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6%250ARmxhc2hIYXNoewAGOgpAdXNlZHsAOgdpZCIlMjRiNDllOTkxMDA4MzIxYTQy%250AMmY3ZWE5ZThiYjQ0Yzk6D2NyZWF0ZWRfYXRsKwi9HzA3NQE%253D--649baaf977e3132be50e8b3dfd98fc7af8f78829; __utmc=43838368

HTTP/1.1 200 OK
Date: Wed, 01 Feb 2012 16:51:27 GMT
Status: 200 OK
X-Transaction: af884ba05db632e8
X-RateLimit-Limit: 350
Etag: "21223203a18f069d32471f270276205c"
X-Frame-Options: SAMEORIGIN
Last-Modified: Wed, 01 Feb 2012 16:51:27 GMT
X-RateLimit-Remaining: 349
X-Runtime: 0.12847
X-Transaction-Mask: a6183ffa5f8ca943ff1b53b5644ef114df9f962d
Content-Type: application/json; charset=utf-8
Pragma: no-cache
X-Access-Level: read-write-directmessages
X-RateLimit-Class: api_identified
X-Revision: DEV
Expires: Tue, 31 Mar 1981 05:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
X-MID: 2bbdd4e107babc4da00b507109079941da57ab7e
X-RateLimit-Reset: 1328118687
Set-Cookie: dnt=; domain=.twitter.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT
Set-Cookie: _twitter_sess=BAh7CjoMY3NyZl9pZCIlNDQwODk0MGMzODA5MTRhODM5M2VlMTk0ZWVlNzVl%250ANWM6B3VhMDoHaWQiJTI0YjQ5ZTk5MTAwODMyMWE0MjJmN2VhOWU4YmI0NGM5%250AIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNo%250AewAGOgpAdXNlZHsAOg9jcmVhdGVkX2F0bCsIvR8wNzUB--466c019301fc4126027ae125b36e3ee87df9df2d; domain=.twitter.com; path=/; HttpOnly
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 854
Server: tfe

Here are the headers when jQuery makes the request:

GET /1/account/verify_credentials.json?callback=jQuery16208501537310110119_1328115220862&oauth_consumer_key=j17jEJEZhnNPxoJMIgejg&oauth_nonce=f0bb96a52da3606e41699a230c948813&oauth_signature=4NuJtynrWLOZOLpYx2KAcPeN3cc%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1328115213&oauth_version=1.0&_=1328115220867 HTTP/1.1
Host: api.twitter.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
Accept: */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://tweetvision.com.php5-19.dfw1-2.websitetestlink.com/get
Cookie: pid=v1%3A1327564106771214543541; k=10.34.124.113.1328070795184680; guest_id=v1%3A132807079518878852; __utma=43838368.683966938.1328070823.1328070823.1328114753.2; __utmz=43838368.1328070823.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmb=43838368.2.10.1328114753; lang=en; twid=u%3D29741933%7CCaWywqVF2Rt%2B%2FIEXdtQoA1JG6gg%3D; _twitter_sess=BAh7CjoMY3NyZl9pZCIlNDQwODk0MGMzODA5MTRhODM5M2VlMTk0ZWVlNzVl%250ANWM6B3VhMDoHaWQiJTI0YjQ5ZTk5MTAwODMyMWE0MjJmN2VhOWU4YmI0NGM5%250AIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNo%250AewAGOgpAdXNlZHsAOg9jcmVhdGVkX2F0bCsIvR8wNzUB--466c019301fc4126027ae125b36e3ee87df9df2d; __utmc=43838368

HTTP/1.1 401 Unauthorized
Date: Wed, 01 Feb 2012 16:53:34 GMT
Status: 401 Unauthorized
WWW-Authenticate: OAuth realm="https://api.twitter.com"
X-Runtime: 0.00514
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache, max-age=300
Set-Cookie: original_referer=4bfz%2B%2BmebEllWaQ%2FEJc%2BxfTCdvqELy6Bo0rf7ub7sygjerfjxiUrzGh9AhVeMb861HOaTBjsVRF0ct%2F%2FwUCIbA%3D%3D; path=/
Set-Cookie: _twitter_sess=BAh7CjoMY3NyZl9pZCIlNDQwODk0MGMzODA5MTRhODM5M2VlMTk0ZWVlNzVl%250ANWM6B3VhMCIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZs%250AYXNoSGFzaHsABjoKQHVzZWR7ADoHaWQiJTI0YjQ5ZTk5MTAwODMyMWE0MjJm%250AN2VhOWU4YmI0NGM5Og9jcmVhdGVkX2F0bCsIvR8wNzUB--9d21303349f9fbfd1f103b31a24ee38c7dc7b611; domain=.twitter.com; path=/; HttpOnly
Expires: Wed, 01 Feb 2012 16:58:34 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 301
Server: tfe

2 years 11 weeks ago
episod
@episod Taylor Singletary

Can you share the bit of jQuery you use in this instance?

2 years 11 weeks ago
kurisa12
@kurisa12 willard kurisa

can you share this code please?

1 year 39 weeks ago
JustinCM
@JustinCM Justin Moses

I abandoned this idea and no longer have the code I was using. It is best to just make the calls from PHP or whatever server-side language. I use a lot of AJAX so my JavaScript just calls my own web-server which makes the OAUTH request to twitter, and then passes back the response to JS. I didn't think it would work out with rate-limits... but it does. Search is the only service you have to use JS for to avoid rate limits, and luckily search twitter's API does not require OAUTH.

1 year 39 weeks ago
JustinCM
@JustinCM Justin Moses

If a server hits it's rate-limit for unauthenticated requests, would that cause users who are using OAUTH on that same server to hit their rate-limit, or are the two completely independent?

2 years 10 weeks ago
episod
@episod Taylor Singletary

The authenticated pool and the unauthenticated pool are independent.

2 years 9 weeks ago
HerdianaJones
@HerdianaJones Herdiana Jones

Hi,
Why I saw this error : "There was an error parsing the JSON document. The document may not be well-formed." when I input this query in address bar : https://api.twitter.com/1.1/search/tweets.json?q=%23freebandnames&since_id=24012619984051000&max_id=250126199840518145&result_type=mixed&count=4 . Why this happen? Thanks before.

1 year 31 weeks ago
episod
@episod Taylor Singletary

I'm not sure why you might have gotten that response -- overall though, you can't take v1.1 URLs and put them in an address bar. You need to use full OAuth to request such URLs.

1 year 31 weeks ago
walking_fishy
@walking_fishy Martin Blackburn

If you were using a custom twitter feed to just pull in tweets to your website, so you could style it better then the old twitter widget, you can try this. It may work for you.

http://www.martinblackburn.co.uk/blog/creating-a-custom-twitter-feed.html

45 weeks 14 hours ago
timacheson
@timacheson Tim Acheson

Yes -- you could continue using the API in JavaScript/JQuery as before. One easy way is just to add a small extra bit of code to act as a proxy between your JavaScript and the API. Looks like you're already half way there.

E.g. How to use Twitter API 1.1 in JavaScript code, bypassing oAuth authentication on the client-side:

http://www.timacheson.com/Blog/2013/jul/twitter_api_prox

42 weeks 13 hours ago
saravan68005674
@saravan68005674 saravanan

hi,
This is not working http://www.timacheson.com/Blog/2013/jul/twitter_api_prox

How to use Twitter API 1.1 in JavaScript code, bypassing oAuth authentication on the client-side. If it is possible give the solution.

28 weeks 3 days ago
Magnum_Revolver
@Magnum_Revolver Osowo de Tut

Please I need help, on using Tweepy.
url links are converted to t.co*******,
i need some particular links to appear as display_url string,
so that I track and count how many times the display_url appears in the tweet trends.
thank you

1 week 6 days ago