2

I've implemented OmniAuth + Twitter strategy. It works most of the time for most users. But some users have been getting a consistent failure, and I have not been able to reproduce it or track it down. After logging in to twitter, the user is redirected to

/auth/failure?message=invalid_credentials

I was able to run an HTTP debugger on one users machine during a failure to see the web traffic, and saw the following:

302 GET       myserver.com/auth/twitter
    CONNECT   api.twitter.com:443
401 GET       myserver.com/auth/twitter/callback?oauth_token=....&oauth_verifier=....
302 GET       myserver.com/auth/twitter/callback?oauth_token=....&oauth_verifier=....
401 GET       myserver.com/auth/failure?message=invalid_credentials&strategy=twitter
302 GET       myserver.com/auth/failure?message=invalid_credentials&strategy=twitter

Once this starts happening for a user, it happens consistently over and over, and even clearing cookies and restarting the browser doesn't fix it. Not sure - but it may be only happening to a user that has logged in the day before and kept their browser open.

I implemented the twitter login in a very lightweight method as you'll see:

user.rb:

class User

  attr_accessor :name, :screen_name, :twitter_secret, :twitter_token

  def initialize(auth)
    @screen_name = auth['info']['nickname']
    @twitter_secret = auth["credentials"]["secret"]
    @twitter_token = auth["credentials"]["token"]
    @name = auth["info"]["name"]
  end

end

session_controller.rb:

class SessionsController < ApplicationController

  def reset_and_auth
    reset_session
    redirect_to '/auth/twitter?force_login=true'
  end

  def create
    user = User.new(request.env["omniauth.auth"])
    session[:current_user] = user
    redirect_to root_path, :notice => "Signed in!"
  end

  def destroy
    session.delete(:current_user)
    redirect_to root_path, :notice => "Signed out!"
  end

  def failure
    flash[:auth_failure] = params[:message]
    redirect_to root_path
  end

end

relevant parts of application_controller.rb:

helper_method :current_user

and

def current_user
  session[:current_user]
end

initializers/omniauth.rb:

twitter_config = YAML.load_file(File.join(Rails.root,'config','twitter.yml'))[Rails.env]

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, twitter_config['consumer_key'], twitter_config['consumer_secret']
end

Other notes of interest (after much googling)

  • This is running on Heroku, so I don't think server Time sync could be the issue
  • The app on dev.twitter.com is configured with a matching callback URL, and a matching hostname
  • The keys and tokens are obviously correct, because it works for most users, most of the time
  • This can't be a problem of actual wrong credentials, because in that case the user gets a message about the password being wrong on the twitter login page and doesn't get redirected
  • Once this happens to one user, it happens consistently and they can't login on that browser. However they can login on a different browser. Also about a day or so later they can login again
  • From browsing the source of the oauth gem, I think it is raising an ::OAuth::Unauthorized exception here https://github.com/intridea/omniauth-oauth/blob/master/lib/omniauth/strategies/oauth.rb

Gem versions:

oauth (0.4.6)
omniauth (1.1.0)
  hashie (~> 1.2)
  rack
omniauth-oauth (1.0.1)
  oauth
  omniauth (~> 1.0)
omniauth-twitter (0.0.12)
  multi_json (~> 1.3)
  omniauth-oauth (~> 1.0)
rails (3.2.6)
4

0 回答 0