0

I've been pulling my hair for hours on this one... I have a Devise and omniauth setup that allows users to log in with their Facebook accounts. I am using the following gem versions:

Installing devise (1.4.7)
Installing oauth2 (0.4.1)
Installing oa-oauth (0.2.6)
Installing omniauth (0.2.6)

among others and have the app id and secret in my Devise initializer:

config.omniauth :facebook, 'app_id', 'app_secret',
          {:scope => 'email, offline_access', :client_options => {:ssl => {:verify => false}}}

Though I also tried this with no luck:

config.omniauth :facebook, 'app_id', 'app_secret',
          # {:scope => 'email, offline_access', :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}}

I have the :omniauthable directive in my user model, and I define my own callback controller in the routes file:

devise_for :users, :controllers => { :omniauth_callbacks => 'user/authentications', :registrations => 'registrations' }

root :to => 'pages#home'

And I also tried adding this to the routes file with no luck:

get '/users/auth/:provider' => 'user/authentications#passthru'

Here is my authentications controller:

class AuthenticationsController < Devise::OmniauthCallbacksController
  def index
    @authentications = current_user.authentications if current_user
  end

  def facebook
    omniauth = request.env["omniauth.auth"]
    authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
    if authentication
      flash[:notice] = "Signed in successfully."
      sign_in_and_redirect(:user, authentication.user)
    elsif current_user
      current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
      flash[:notice] = "Authentication successful."
      redirect_to authentications_url
    else
      user = User.new
      user.apply_omniauth(omniauth)
      if user.save
        flash[:notice] = "Signed in successfully."
        sign_in_and_redirect(:user, user)
      else
        session[:omniauth] = omniauth.except('extra')
        redirect_to new_user_registration_url
      end
    end
  end

  def passthru
    render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
  end

  def destroy
    @authentication = current_user.authentications.find(params[:id])
    @authentication.destroy
    flash[:notice] = "Successfully destroyed authentication."
    redirect_to authentications_url
  end
end

And my Facebook log in link:

<%= link_to image_tag('/assets/facebook_32.png'), omniauth_authorize_path(resource_name, :facebook)%>

This all works great locally, but if I try to log in with my Facebook account when my app is deployed to Heroku, I get the following in my log and I'm directed to the 404 page:

2011-09-23T03:26:31+00:00 app[web.1]: ActionController::RoutingError (uninitiali
zed constant User::AuthenticationsController):

I tried resetting my database, but that didn't help either.

Here are my routes from Heroku:

        new_user_session GET    /users/sign_in(.:format)               {:action=
>"new", :controller=>"devise/sessions"}
            user_session POST   /users/sign_in(.:format)               {:action=
>"create", :controller=>"devise/sessions"}
    destroy_user_session GET    /users/sign_out(.:format)              {:action=
>"destroy", :controller=>"devise/sessions"}
  user_omniauth_callback        /users/auth/:action/callback(.:format) {:action=
>/facebook/, :controller=>"user/authentications"}
           user_password POST   /users/password(.:format)              {:action=
>"create", :controller=>"devise/passwords"}
       new_user_password GET    /users/password/new(.:format)          {:action=
>"new", :controller=>"devise/passwords"}
      edit_user_password GET    /users/password/edit(.:format)         {:action=
>"edit", :controller=>"devise/passwords"}
                         PUT    /users/password(.:format)              {:action=
>"update", :controller=>"devise/passwords"}
cancel_user_registration GET    /users/cancel(.:format)                {:action=
>"cancel", :controller=>"registrations"}
       user_registration POST   /users(.:format)                       {:action=
>"create", :controller=>"registrations"}
   new_user_registration GET    /users/sign_up(.:format)               {:action=
>"new", :controller=>"registrations"}
  edit_user_registration GET    /users/edit(.:format)                  {:action=
>"edit", :controller=>"registrations"}
                         PUT    /users(.:format)                       {:action=
>"update", :controller=>"registrations"}
                         DELETE /users(.:format)                       {:action=
>"destroy", :controller=>"registrations"}
                    root        /                                      {:control
ler=>"pages", :action=>"home"}

Any help is greatly appreciated. Please let me know if you need any other info. I know it's something small, but I feel like I've tried a thousand different things and nothing has worked.

TK Gospodinov
  • 8,302
  • 6
  • 24
  • 25

2 Answers2

0

I think, your authenicatine line should be using find_or_create.

authentication = Authentication.find_or_create_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
Rishav Rastogi
  • 15,484
  • 3
  • 42
  • 47
  • I am checking if the authentication is nil after looking it up. If it is nil, it gets created further down that method in my controller. – TK Gospodinov Sep 23 '11 at 15:07
0

I ended up changing

devise_for :users, :controllers => { :omniauth_callbacks => 'user/authentications', :registrations => 'registrations' }

to

devise_for :users, :controllers => { :omniauth_callbacks => 'authentications', :registrations => 'registrations' }

and it started working both locally and on Heroku.

TK Gospodinov
  • 8,302
  • 6
  • 24
  • 25