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)