Authlogic Facebook Connect Snafu
authlogic, facebook, ruby-on-rails
Solution
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:
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`
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
- 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
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
- In the first step you created a file to get config data from facebooker.yml
- 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
- 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...
Problem
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!