Facebook Connect with Rails (using Omniauth and Devise) [Update]

This is an update to my last post about Facebook Connect with a Rails app. At the time I was using facebooker plugin (yeah, a plugin, not a gem), which has been discontinued for the longest time, and thus wouldn’t work with current Facebook connect.

Since then, I’ve used omniauth, omniauth-facebook, and devise gems to implement Facebook connect with a few Rails app I have been toying with. So, this is kind of an update to my last post about integrating Facebook Connect with a Rails app.

1. First, you need the following gems in your Gemfile.

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

Make sure you install them by running “bundle install” command.

2. Next configure devise gem.

rails generate devise:install

3. Apply devise to a model. 99.9% of time, this would be the User model.

rails generate devise User

4. Next, generate authentication model with the following columns. Token column is extra, if you want to save an access token.

rails g model Authentication user_id:integer provider:string uid:string token:string

5. Configure omniauth by modifying config/initializers/omniauth.rb

Rails.application.config.middleware.use OmniAuth::Builder do
  # The following is for facebook
  provider :facebook, [APP ID], [SECRET KEY], {:scope => 'email, read_stream, read_friendlists, friends_likes, friends_status, offline_access'}

  # If you want to also configure for additional login services, they would be configured here.
end

6. After user authenticates with whatever provider you specify, user needs to be redirected to omniauth call, so add the following line in your routes.rb.

match '/auth/:provider/callback' => 'authentications#create'

7. Then in Authentications controller, you figure out whether to create a new user or log the user in, if the user is an existing user. For complete hash, take a look at omniauth-facebook github page.

def create
  auth = request.env["omniauth.auth"]

  # Try to find authentication first
  authentication = Authentication.find_by_provider_and_uid(auth['provider'], auth['uid'])

  if authentication
    # Authentication found, sign the user in.
    flash[:notice] = "Signed in successfully."
    sign_in_and_redirect(:user, authentication.user)
  else
    # Authentication not found, thus a new user.
    user = User.new
    user.apply_omniauth(auth)
    if user.save(:validate => false)
      flash[:notice] = "Account created and signed in successfully."
      sign_in_and_redirect(:user, user)
    else
      flash[:error] = "Error while creating a user account. Please try again."
      redirect_to root_url
    end
  end
end

8. In User model, store essential information with apply_omniauth method.

has_many :authentications, :dependent => :delete_all
def apply_omniauth(auth)
  # In previous omniauth, 'user_info' was used in place of 'raw_info'
  self.email = auth['extra']['raw_info']['email']
  # Again, saving token is optional. If you haven't created the column in authentications table, this will fail
  authentications.build(:provider => auth['provider'], :uid => auth['uid'], :token => auth['credentials']['token'])
end

9. In Authenication model,

belongs_to :user

10. In your view, user clicking on /auth/facebook/ link will be redirected to Facebook to log in.

<%= link_to 'Login with Facebook', '/auth/facebook/' %>

11. This method doesn’t do FB login in a popup. For that, you have to use FB Javascript SDK, and you can use the example here.

How to integrate Facebook Feed with a Rails app

On Monday, I’ve gotten Facebook Feed publishing to work with my site, and it took about two hours including TV watching time. I could’ve done it faster if I actually paid a full attention. It was all possible, thanks to Chris Schmitt, who has an excellent tutorial on his site.

1. Simply you first need to create a sub-class inherited from Facebooker::Rails::Publisher inside a controller. In my case, I wanted to publish a feed when a new playground is added and an existing playground is edited, so it made a sense to put it in playgrounds controller. publish_pg takes objects and sets parameters, and publish_pg_template creates a feed message based on those parameters.

class PlaygroundsController < ApplicationController

[SNIP - other actions]

  class FacebookPublisher < Facebooker::Rails::Publisher

    def publish_pg_template
      one_line_story_template "{*actor*} created/updated: {*pg_name*}"
      short_story_template "{*actor*} created/updated: {*pg_name*} in {*pg_city*}, {*pg_state*}",
                           "Check out what {*actor*} said, and rate or add comments to help other parents!"
    end

    def publish_pg(pg, facebook_session)
      send_as :user_action
      from facebook_session.user
      data :actor => facebook_session.user.first_name, :pg_name => pg.name, :pg_city => pg.city, :pg_state => pg.state, :pg_id => pg.id
    end

  end

end

Continue reading

How to integrate Facebook Connect with a Rails app

Update: I have written up another post for using Devise and Omniauth, and you can find it here. Facebooker is no longer maintained.

Top of my to-do list was to integrate Facebook Connect with my Rails app, since 1) there are A LOT of people using Facebook and 2) having to register to post or edit could be an obstacle in getting more users to use my site.

I looked on the web for a while, and found a great example by Stuart Eccles at Made by Many. It’s an awesome tutorial, but it’s for restful_authentication. I don’t use it, so I had to modify it a little bit. Also, I added a step to ask a user to pick a username. So the following instruction is basically modification of Stuart’s.

Without further ado, let’s begin.

1. Setup Facebook Application page

1.1. Go to this page, and enter a name for your application. I named mine “Playgrounds_R_Us”.

1.2. Make a note of Application ID, API Key, and Secret. You need it for facebooker.yml later.

1.3. Next is Authentication section. Here what’s important is Post-Authroize and Post-Remove Callback URL. They refer to a web page a user will be taken to after logging into and logging out of Facebook account. While testing, I left it at “http://127.0.0.1:3000”.

1.4. I also used the same URL (http://127.0.0.1:3000) for Canvas Callback URL in Canvas section and Connect URL in Connect section.

1.5. Then you are pretty much set with configuration on Facebook side.

2. Get facebooker plugin and install it. From your rails app root directory,

ruby script/plugin install git://github.com/mmangino/facebooker.git

Continue reading