3

I have Devise authentication installed with no problems. Now I'm trying to add an option to log in with Facebook, using Omniauth-facebook.

I followed the instructions in this guide, but I'm getting errors about missing "Passthru" documentation, when visiting the url localhost:3000/auth/facebook.

Here's the first error I got:

Unknown action
The action 'passthru' could not be found for RegistrationsController

I tried a bandaid fix by just adding an empty "passthru" action to my controller:

def passthru
end

And that resolved that error, but I got a different one in return:

Template is missing
Missing template registrations/passthru, devise/registrations/passthru, devise/passthru, application/passthru with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in: * "/home/user/project/app/views" * "/home/user/.rvm/gems/ruby-2.0.0-p648@railstutorial_rails_4_0/gems/devise-3.5.2/app/views"

I tried creating a "passthru.html.erb" in the stated folders, but that error remained. In any case, I think these errors are emblematic of a deeper problem.

Has anyone else run into this problem? All I could find on it was this SO question, but none of the answers were helpful.


My code so far:

Gemfile

gem 'devise'
gem 'omniauth-facebook'
gem 'omniauth'

routes.rb

devise_for :members, controllers: { registrations: 'registrations', omniauth_callbacks: 'registrations' }

member.rb

  devise :database_authenticatable, :registerable,
         :omniauthable, :omniauth_providers => [:facebook]


  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |member|
      member.email = auth.info.email
      member.password = Devise.friendly_token[0,20]
      member.title = auth.info.name
    end
  end

registrations_controller.rb

  def facebook
    @member = Member.from_omniauth(request.env["omniauth.auth"])
    if @member.persisted?
      sign_in_and_redirect @member, :event => :authentication
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_member_registration_url
    end
  end

  def failure
    redirect_to root_path
  end

  def passthru
  end

initializers/devise.rb

config.omniauth :facebook, "<app_id>", "<app_secret>"
Community
  • 1
  • 1
Joe Morano
  • 1,715
  • 10
  • 50
  • 114
  • Please describe what are you trying to achieve by `passthru` method? – Pravesh Khatri May 25 '16 at 04:33
  • @PraveshKhatri I don't want to do anything with it. The documentation doesn't say anything about passthru either. I think it's a relic from an old version of omniauth. – Joe Morano May 25 '16 at 04:36

5 Answers5

2

Try this :

Update GemFile:

gem 'omniauth-facebook'
gem 'omniauth'

Goto rails_apps/yourapp/config/initializers/devise.rb

Devise.setup do |config|
   config.omniauth :facebook, "KEY", "SECRET"
 end

Update the User Model

class User < ActiveRecord::Base

         devise :database_authenticatable, :registerable,
        :recoverable, :rememberable, :trackable, :validatable,
    :omniauthable, :omniauth_providers => [:facebook]

     def self.from_omniauth(auth)
         where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
           user.provider = auth.provider
           user.uid = auth.uid
           user.email = auth.info.email
           user.password = Devise.friendly_token[0,20]
         end
     end
    end

Goto : rails_apps/yourapp/config/routes.rb

Rails.application.routes.draw do
  devise_for :users
  resources :users
end

Edit in View

 <%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %>
vipin
  • 2,374
  • 1
  • 19
  • 36
1

Passthru is a relic from omniauth update your gems of devise omniauth and so on . there is a controller called omiauth_callback this is the one makes noizes ;P.(may help you trace the problem's source)

If you create a method in controller like so : def passthru end You HAVE TO create a view with(even empty), or redirection :get inspired by ajax techniques to bypass html rendering . Hope it send you on the way of problem solving .

try also theses routes : ``` user_omniauth_authorize /users/auth/:provider(.:format) sessions#passthru {:provider=>/facebook|twitter|google/}

user_omniauth_callback /users/auth/:action/callback(.:format) sessions#(?-mix:facebook|twitter|google) ```

plombix
  • 396
  • 3
  • 13
  • I just wrote "gem 'omniauth-facebook'" and that was about a week ago, so shouldn't I automatically have the latest version? – Joe Morano May 31 '16 at 03:50
  • Humm depends of Gemfile.lock verify this file , and if necessary : gem upgrade gem_name . Btw : def passthru; render :layout => false ; end – plombix May 31 '16 at 19:02
  • ``` user_omniauth_authorize /users/auth/:provider(.:format) sessions#passthru {:provider=>/facebook|twitter|google/} user_omniauth_callback /users/auth/:action/callback(.:format) sessions#(?-mix:facebook|twitter|google). ``` – plombix May 31 '16 at 19:05
0

You can create another controller for Omniauth callback

class OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def facebook
    @user =  User.from_omniauth(request.env['omniauth.auth'])
    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication 
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end


  def after_sign_in_path_for(resource)
    super resource
  end

end

you need to reset your routes as

devise_for :members, :controllers => {:registrations => "members/registrations", :omniauth_callbacks => 'omniauth_callbacks'}

As i could remember you need not to use :omniauth_providers => [:facebook] in your member.rb

Now you can add a button in your sign_up page or instead include the below code in your devise/shared/_links.html.erb, because it will be available in your sign_in form also.

<%- if devise_mapping.omniauthable? %>
  <%- resource_class.omniauth_providers.each do |provider| %>
    <%= link_to "Sign up with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), class: "btn btn-default navbar-btn" %><br />
  <% end -%>
<% end -%>

you also need to configure devise in initializers

In your /config/initializers/devise.rb

config.omniauth :facebook, "App ID", "App Secret", scope: 'email', info_fields: 'email,name'

Please go through this simplest tutorial for Sing_up with facebook Link

Pravesh Khatri
  • 2,124
  • 16
  • 22
  • Are you sure I need a separate controller for Omniauth Callback? Why would it matter what controller it's in, as long as the route points to the correct one? – Joe Morano May 25 '16 at 04:58
  • yes, you can do it in same controller but I usually do it in another controller, since It makes me clear that if I need to Include sign up with other social media like twitter, linkedIn, etc. then It will not make a mess in my registrations controller. – Pravesh Khatri May 25 '16 at 05:13
  • Yeah, so I think that other than that, I have the same code you posted. – Joe Morano May 25 '16 at 22:57
0

Try this .........

config/initializers/devise.rb

config.omniauth :facebook, ENV["FACEBOOK_KEY"], ENV["FACEBOOK_SECRET"], { :scope => 'email, offline_access'}

config/routes.rb

devise_for :members, controllers: { registrations: 'registrations', omniauth_callbacks: "omniauth_callbacks" }

app/models/member.rb

devise :database_authenticatable, :registerable,
      :recoverable, :rememberable, :trackable, :validatable, :omniauthable


def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |member|
    member.email = auth.info.email
    member.password = Devise.friendly_token[0,20]
    member.title = auth.info.name
  end
end 

app/controllers/omniauth_callbacks_controller.rb

  skip_before_filter :authenticate_user!

  def facebook
    p env["omniauth.auth"]
    user = User.from_omniauth(env["omniauth.auth"])
    if user.persisted?
      flash[:notice] = "You are in..!!!"
      sign_in_and_redirect(user)
    else
      session["devise.user_attributes"] = user.attributes
      redirect_to new_user_registration_url
    end
  end

  def failure
    #handle you logic here..
    #and delegate to super.
    super
  end

Hope this will work for you.

Akshay Borade
  • 2,442
  • 12
  • 26
  • What's the difference in our code that you think might be causing my error? I can't find any meaningful difference. – Joe Morano May 27 '16 at 18:09
0

I think the problem is always on the button or the anchor, so use this

<%= link_to user_facebook_omniauth_authorize_path, method: :post do %>
login with facebook 
<% end %>
ramzieus
  • 138
  • 11