Devise with OmniAuth Facebook
<p>I'm stuck with integrating <code>devise</code> with <code>omniauth-facebook</code></p>

<p>My demo app is using:</p>

<ul>
<li>Rails 5</li>
<li>Devise </li>
<li>Pundit</li>
<li>OmniAuth (omniauth-facebook)</li>
</ul>

<p>I followed the following guide on the Wiki page: <a href="https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview" rel="nofollow">https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview</a> but having problems creating the user.</p>

<p>It will sign-in the user and add the app to the user's Facebook (in App Settings) but it does register the account to the <code>User</code> model.</p>

<pre><code># Gemfile
source 'https://rubygems.org'

gem 'rails', '~&gt; 5.0.0'

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

# Gemfile.lock for the 3 authorization and authentication gems
GEM
  remote: https://rubygems.org/
  remote: https://rails-assets.org/
  specs:

    devise (4.2.0)
      bcrypt (~&gt; 3.0)
      orm_adapter (~&gt; 0.1)
      railties (&gt;= 4.1.0, &lt; 5.1)
      responders

      warden (~&gt; 1.2.3)
    pundit (1.1.0)

    omniauth (1.3.1)
      hashie (&gt;= 1.2, &lt; 4)
      rack (&gt;= 1.0, &lt; 3)
    omniauth-facebook (4.0.0)
      omniauth-oauth2 (~&gt; 1.2)
    omniauth-oauth2 (1.4.0)
      oauth2 (~&gt; 1.0)
      omniauth (~&gt; 1.2)
</code></pre>

<p>The schema for the User model.</p>

<p>I added a migration <code>provider:string</code> and <code>uid:string</code></p>

<pre><code># == Schema Information
#
# Table name: users
#
#  id                     :integer          not null, primary key
#  email                  :string           default(""), not null
#  encrypted_password     :string           default(""), not null
#  reset_password_token   :string
#  reset_password_sent_at :datetime
#  remember_created_at    :datetime
#  sign_in_count          :integer          default(0), not null
#  current_sign_in_at     :datetime
#  last_sign_in_at        :datetime
#  current_sign_in_ip     :inet
#  last_sign_in_ip        :inet
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#  name                   :string           default(""), not null
#  provider               :string
#  uid                    :string
</code></pre>

<p>The <code>ApplicationController</code> contains <code>pundit</code> and <code>devise</code> code:</p>

<pre><code>class ApplicationController &lt; ActionController::Base
  include Pundit
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?

  private

    def user_not_authorized
      flash[:error] = "You are not authorized to perform this action."
      redirect_to(request.referrer || root_path)
    end

  protected

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
      devise_parameter_sanitizer.permit(:account_update, keys: [:name])
    end
end
</code></pre>

<p>I've configured <code>config/initializers/devise.rb</code> to include <code>:facebook</code> in the <code>omniauth</code> config.</p>

<pre><code># File: config/initializers/devise.rb
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
  require 'devise/orm/active_record'

  config.case_insensitive_keys = [:email]
  config.strip_whitespace_keys = [:email]
  config.skip_session_storage = [:http_auth]
  config.stretches = Rails.env.test? ? 1 : 11
  config.reconfirmable = true
  config.password_length = 6..128
  config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
  config.sign_out_via = :delete

  # ==&gt; OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], callback_url: ENV['FACEBOOK_CALLBACK_URL'], scope: 'email', info_fields: 'email,name'
end
</code></pre>

<p>I've added <code>omniauthable</code> to the <code>User</code> model.</p>

<pre><code>class User &lt; ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  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.name = auth.info.name
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
    end
  end

  def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.facebook_data"] &amp;&amp; session["devise.facebook_data"]["extra"]["raw_info"]
        user.email = data["email"] if user.email.blank?
      end
    end
  end
end
</code></pre>

<p>I've created an <code>OmniauthCallbacksController</code> to handle sign-in requests.</p>

<pre><code># File: app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController &lt; Devise::OmniauthCallbacksController
  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
      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 failure
    redirect_to root_path
  end
end
</code></pre>

<p>In the <code>Routes</code> I've added the following:</p>

<pre><code># File: config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }

  root 'pages#index'
end
</code></pre>

<p>Added "Sign in with Facebook" link to <code>devise</code> <code>sessions#new</code> view.</p>

<pre><code># File: app/views/devise/sessions/new.html.erb
&lt;div class="login"&gt;
  &lt;%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path %&gt;
 # This is the link it creates: &lt;a href="/users/auth/facebook"&gt;Sign in with Facebook&lt;/a&gt;
&lt;/div&gt;
</code></pre>

<hr>

<h3>User flow:</h3>

<ol>
<li>Clicks the "Sign in with Facebook"</li>
<li>User gets forwarded to Facebook's Oauth url with 'Continue as User' prompt where user clicks "OK"</li>
<li>User is returned to the app but user isn't registered in the database</li>
<li>The url is a long string of params <code>code</code> and <code>state</code> (check *NB</li>
</ol>

<p>*NB Return url from Facebook:</p>

<pre><code>http://localhost:3000/?code=REALLYLONGHASHOFCHARACTERS&amp;state=ANOTHERSETOFREALLYLONGHASHOFCHARACTERS
</code></pre>

<p>The development.log show:</p>

<pre><code>Started GET "/users/auth/facebook" for ::1 at 2016-08-10 18:43:26 +1000
I, [2016-08-10T18:43:26.084371 #2292]  INFO -- omniauth: (facebook) Request phase initiated.
Started GET "/users/auth/facebook" for ::1 at 2016-08-10 18:43:26 +1000
I, [2016-08-10T18:43:26.521627 #2292]  INFO -- omniauth: (facebook) Request phase initiated.
Started GET "/?code=REALLYLONGHASHOFCHARACTERS&amp;state=ANOTHERSETOFREALLYLONGHASHOFCHARACTERS" for ::1 at 2016-08-10 18:44:19 +1000
Processing by ListingsController#index as HTML
  Parameters: {"code"=&gt;"REALLYLONGHASHOFCHARACTERS", "state"=&gt;"ANOTHERSETOFREALLYLONGHASHOFCHARACTERS"}
</code></pre>

<p>I don't think it's hitting <code>Users::OmniauthCallbacksController &lt; Devise::OmniauthCallbacksController</code> because I put a <code>raise "Error"</code> on the <code>facebook</code> action but it doesn't raise any errors. And I can't see the <code>omniauth_callbacks: "users/omniauth_callbacks"</code> when running <code>Rails routes</code></p>

<p>Checking the routes show:</p>

<pre><code># Routes

||                           Prefix Verb     URI Pattern                             Controller#Action
||                 new_user_session GET      /users/sign_in(.:format)                devise/sessions#new
||                     user_session POST     /users/sign_in(.:format)                devise/sessions#create
||             destroy_user_session DELETE   /users/sign_out(.:format)               devise/sessions#destroy
|| user_facebook_omniauth_authorize GET|POST /users/auth/facebook(.:format)          users/omniauth_callbacks#passthru
||  user_facebook_omniauth_callback GET|POST /users/auth/facebook/callback(.:format) users/omniauth_callbacks#facebook
||                    user_password POST     /users/password(.:format)               devise/passwords#create
||                new_user_password GET      /users/password/new(.:format)           devise/passwords#new
||               edit_user_password GET      /users/password/edit(.:format)          devise/passwords#edit
||                                  PATCH    /users/password(.:format)               devise/passwords#update
||                                  PUT      /users/password(.:format)               devise/passwords#update
||         cancel_user_registration GET      /users/cancel(.:format)                 devise/registrations#cancel
||                user_registration POST     /users(.:format)                        devise/registrations#create
||            new_user_registration GET      /users/sign_up(.:format)                devise/registrations#new
||           edit_user_registration GET      /users/edit(.:format)                   devise/registrations#edit
||                                  PATCH    /users(.:format)                        devise/registrations#update
||                                  PUT      /users(.:format)                        devise/registrations#update
||                                  DELETE   /users(.:format)                        devise/registrations#destroy
||                             root GET      /                                       pages#index
</code></pre>

<p>I'm not sure what to do from here. Any help and insight is much appreciated.</p>