41

I am using the ruby twitter gem and oauth to gain access to users twitter accounts. In my code, I have:

unless @user.twitter_authd?
      oauth = Twitter::OAuth.new('token', 'secret')
      session[:twitter_request_token] = oauth.request_token.token
      session[:twitter_request_secret] = oauth.request_token.secret
      @twitter_auth_url = oauth.request_token.authorize_url
    end

where token and secret have my actual token and secret inserted. When I click on the link to the @twitter_auth_url, I am taken to twitter and asked to grant access. I click allow and then twitter redirects me to my callback URL http://www.mydomain.com/twitter_callback/?oauth_token=fmy2aMvnjVgaFrz37bJ4JuB8r5xN79gsgDQRG4BNY which then hits this code:

oauth = Twitter::OAuth.new('token', 'secret')

    logger.info("session[:twitter_request_token] = #{session[:twitter_request_token]}")
    logger.info("session[:twitter_request_secret] = #{session[:twitter_request_secret]}")

    oauth.authorize_from_request(session[:twitter_request_token], session[:twitter_request_secret])
    session[:twitter_request_token] = nil
    session[:twitter_request_secret] = nil

    @user.update_attributes({
      :twitter_token => oauth.access_token.token, 
      :twitter_secret => oauth.access_token.secret,
    })

    redirect_to root_path

The twitter request token and secret are being set just fine. However I end up with an authorization error:

 OAuth::Unauthorized in MainController#twitter_callback

401 Unauthorized

RAILS_ROOT: /Users/TAmoyal/Desktop/RoR_Projects/mls
Application Trace | Framework Trace | Full Trace

/Library/Ruby/Gems/1.8/gems/oauth-0.3.4/lib/oauth/consumer.rb:167:in `token_request'
/Library/Ruby/Gems/1.8/gems/oauth-0.3.4/lib/oauth/tokens/request_token.rb:14:in `get_access_token'
/Library/Ruby/Gems/1.8/gems/erwaller-twitter-0.6.13.1/lib/twitter/oauth.rb:29:in `authorize_from_request'
/Users/TAmoyal/Desktop/RoR_Projects/mls/app/controllers/main_controller.rb:70:in `twitter_callback'

The code is failing at this line:

oauth.authorize_from_request(session[:twitter_request_token], session[:twitter_request_secret])

when it tries to get an access token. You can see the source code of authorize_from_request here. I am not sure why this is happening. Anyone have ideas?

Tony
  • 18,776
  • 31
  • 129
  • 193

8 Answers8

78

A bit late to the party but just ran into the same issue myself. I tracked the issue down to the setup of my OAuth app in Twitter. I had initially not specified a callback URL as I was unsure of it.

Once I had setup my rails app I went back to find Twitter had assumed I was a desktop application as I hadn't specified a callback URL. Once I changed this to website and entered a callback URL I stopped getting 400s.

George Palmer
  • 781
  • 5
  • 2
  • what's actually the difference between desktop and web application? – Radek Apr 10 '10 at 09:39
  • @Radek - desktop and web are essentially the same. However, desktop apps can't have a callback URL as part of the authorisation process. Instead twitter generates a PIN number which is then shown to the user and they enter it into the desktop app. – Dan Diplo Jul 30 '10 at 14:36
  • @Dan Diplo: thank you for the explanation. Still wondering how the callback URL works. Is it the same url all the time and all info is stored only in headers? – Radek Aug 03 '10 at 06:07
  • @Radek - You register the callback URL when you register your app with Twitter. However, you can also specify the callback URL in your authentication request, too, which over-rides this and allows it to be dynamic. All of info is passed as headers, but it is up to the consuming app to store the final token and secret. See http://dev.twitter.com/pages/auth – Dan Diplo Aug 03 '10 at 08:58
  • 2
    What tripped me up: although you can override the callback URL in the request, if you do not enter ~something~ as the callback url when registering the application at twitter, then twitter defaults your settings back to a "client application". You won't notice this unless you go back in to edit the settings again. – tardate Oct 31 '10 at 10:01
  • Worked for me by setting 'http://127.0.0.1:3000/auth/twitter/callback' as the callback URL for local testing. – sunsations Aug 15 '13 at 12:47
30

If you're getting error 401 - OAuth::Unauthorized, make sure you edit the settings of your Twitter application as follows:

Hatem Mahmoud
  • 403
  • 6
  • 9
8

this is an issue about time synchronization of your system with twitter server.

Rabia
  • 81
  • 1
  • 1
  • 2
    If your server time is way out (e.g. virtual machine clock has wandered off into the sunset) then you will get a "Twitter OAuth 401 Unauthorized" error (if you're using OAuth gem, for example). Changing the time does fix this issue. – RidingTheRails Jan 08 '13 at 15:19
  • Thank you so much! This was getting to be quite a pain. I checked and my VM was not set to sync time with the host in VMWare Fusion. Check the sync time option in advanced settings and it started working immediately. – David Oct 14 '13 at 21:53
8

Twitter doesn't allow localhost as part of a valid callback URL.

Instead use http://127.0.0.1:3000/auth/twitter/callback

Hope this helps

Mulan
  • 129,518
  • 31
  • 228
  • 259
4

This was one of the most annoying things to debug that I have come across. I was outputting in a couple places by accident because the URL's are dynamic and they happened to not be defined in my test case (i use this to display chart data and there is not enough right now so the google chart api URL's are blank). This caused my browser to make multiple requests to my localhost when some pages were loaded. Somehow that made the oauth process crap out. Obviously there is no way for people on S.O. to know about my application specific issue so I had to answer my own question.

Tony
  • 18,776
  • 31
  • 129
  • 193
  • could you elaborate on this a bit? multiple requests as in redirects? or images/static files but within the same request? – Kyle Nov 30 '09 at 16:17
  • it's been a while but i think the idea is that if you have an img tag with an empty source (src="") or maybe i had (src="/"), your browser tries to load your website again for the image. so for every image with an empty source, you get an extra load – Tony Dec 01 '09 at 14:21
  • thanks tony. life saver. do you know why this would cause oauth to crap out? – meow Jun 16 '10 at 09:36
  • honestly, it's been too long for me to remember why. glad this helped. – Tony Jun 16 '10 at 13:18
2

I had this same problem and none of the suggestions in this thread worked for me.

I found the problem for me was the TIMESTAMP on my request. The mobile device I was running my scripts on had a jacked up clock. When I updated the system time on my device to the correct time (i.e. now), all of my requests came back "200 OK" instead of "401 Unauthorized".

Kenny Wyland
  • 20,844
  • 26
  • 117
  • 229
  • So glad you left this solution. Had the same problem with a MacBook Air where the clock was off. I probably would have lost quite a bit of time going down the wrong rabbit holes -- Big thanks Kenny! – jmejia Oct 26 '15 at 00:16
1

This problem seems to be caused by twitter not being able to handle connection keep-alive correctly. Make sure you set connection=close http header in the request to twitter. Wasted a weekend debugging this.

DarkAjax
  • 15,955
  • 11
  • 53
  • 65
vadim
  • 11
  • 1
0

not enough info for me, but when was twitter gem last updated? twitter changed their oauth 'stuff' in mid may approx. perhaps you have an old one. I'd update your question to show the callback_url, and make sure you have the right token and secret, which it looks like you don't have.

also, did you put the right callback url in your twitter app page? alot of times that screws you up too.

if that fails use mbleighs twitter_auth instead. it worked for me and is pretty slick.

pjammer
  • 9,489
  • 5
  • 46
  • 56
  • I added my callback URL to the example. I know people are successfully using the Twitter gem right now, but with oauth 0.3.4 (0.3.5 broke some stuff). As far as the right token and secret, I copied the consumer key and secret straight from my twitter app settings...not sure how those can be wrong. The request token and secret are generated once and saved in the session, so those do not change and I'm not sure how they could be wrong either. what do you mean by "the right callback URL"? I am certainly getting redirected to the right action in my web app...doesn't that mean it's right? – Tony Aug 15 '09 at 16:33