Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authlogic Facebook Connect Snafu

I have an application configured with authlogic and authlogic_facebook_connect, but every time I click to "Connect" button, my UserSession fails validation, saying "You did not provide any details for authentication"

Isn't the authlogic_facebook_connect supposed to bypass login/password authentication? Am I missing some configuration step?

Any help would be appreciated!

like image 371
a10s Avatar asked Mar 08 '10 21:03

a10s


1 Answers

Hey, maybe I can help on this one, just had this problem not very long time ago...

Facebook connect is outdated. All the cool kids are now using Facebook Graph with OAuth. Facebook team have even closed the documentation for Facebook Connect.

Anyway, that goes for Authlogic Facebook connect, it simply does not work anymore.

In the end, I kept using Authlogic for normal login and account management, but for Facebook connect I wrote my own code.

Chances are you may have used facebooker gem. Uninstall that gem, but keep the config/facebooker.yml file.

Try this:

  1. Keep using config/facebooker.yml by adding this code inside config/initializers/load_config.rb (you need to create this file)

    config = YAML.load_file("#{Rails.root}/config/facebooker.yml") || {}

    facebook_config = config['common'] || {}

    facebook_config.update(config[Rails.env] || {})

    FB_CONFIG = facebook_config.symbolize_keys

  2. Add this code inside your user_controller.rb:

def facebook_oauth_callback
  if not params[:code].nil?
    callback = url_for(:host => APP_CONFIG[:host], :controller => 'gallery/user', :action => 'facebook_oauth_callback')
    url = URI.parse("https://graph.facebook.com/oauth/access_token?client_id=#{FB_CONFIG[:application_id]}&redirect_uri=#{callback}&client_secret=#{FB_CONFIG[:secret_key]}&code=#{CGI::escape(params[:code])}")
    http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == 'https') tmp_url = url.path + "?" + url.query
    request = Net::HTTP::Get.new(tmp_url)
    response = http.request(request)
    data = response.body
    access_token = data.split("=")[1]
    if access_token.blank?
      flash[:notice] = 'An error occurred while connecting through Facebook, please try again later.' 
    else
      url = URI.parse("https://graph.facebook.com/me?access_token=#{CGI::escape(access_token)}")
      http = Net::HTTP.new(url.host, url.port)
      http.use_ssl = (url.scheme == 'https')
      tmp_url = url.path + "?" + url.query
      request = Net::HTTP::Get.new(tmp_url)
      response = http.request(request)
      user_data = response.body
      user_data_obj = JSON.parse(user_data)
      @user = User.new_or_find_by_facebook_oauth_access_token(access_token, {:user_data => user_data_obj})

      if @user.new_record?
        session[:user] = @user
        session[:external_app] = "Facebook"
        redirect_to(:action => 'new_details')
      else
        user_session = UserSession.create(@user)
        flash[:notice] = "Successfully logged in."
        redirect_back_or_default root_url
      end
    end
  end
end

def create_facebook
  redirect_to("https://graph.facebook.com/oauth/authorize?client_id=#{FB_CONFIG[:application_id]}&redirect_uri=" + 
    url_for(:host => APP_CONFIG[:host], :controller => 'gallery/user', :action => 'facebook_oauth_callback') + 
    "&scope=email,offline_access")
end
  1. Add the find method inside your User model (app/models/user.rb):
      def self.new_or_find_by_facebook_oauth_access_token(access_token, options = {})
        user = User.find_by_facebook_oauth_access_token(access_token)
        if user.blank?
          #code to create new user here
        end
        user
      end
  1. Add link to action create_facebook in the view, something like

    <%= link_to image_tag('gallery/button-facebook.png', :title => "register with Facebook", :alt => "register with Facebook"), {:action => 'create_facebook'}, {:target => '_parent'} %>

Explanation

  1. In the first step you created a file to get config data from facebooker.yml
  2. In second step, you basically created two functions, one for sending user to facebook site (create_facebook) and another to capture the callback data (facebook_oauth_callback) the idea was from this page: http://www.wisejive.com/2010/05/facebook-oauth-on-rails.html
  3. In third step, you just added a method inside User model to find, or create new if not found, a user based on the information returned from facebook.

The code only works on my project, do not just copy-paste it but learn it line-by-line. Over time I realised it is better to use simple code you can understand rather than using other's complicated plugin you cannot fix when things go awry...

like image 117
jaycode Avatar answered Sep 28 '22 08:09

jaycode