If you have watched Ryan Bates’ tutorial Simple OmniAuth you probably already know OmniAuth is awesome. :) Ryan doesn’t go into details about setting up OmniAuth with Facebook so this post has a couple of pointers to help out in that regard. It’s meant as a continuation to the screencast, so if you haven’t seen it start there.

In particular I had trouble getting the correct Facebook Application settings for development and ran into a silly little issue that took ages to figure out. So here’s more about that.

Create a Facebook App

Log in to your Facebook account and go to http://www.facebook.com/developers

Click the Set Up New App button at the top of the right column.

In the “Website” tab set the Site URL (formerly known as Connect URL) to http://localhost:3000/ and the Domain to localhost.

Facebook Screenshot

In the end your application settings should look something like this.

Configure Omniauth

Add the Facebook App ID and API Key to config/initializers/omniauth.rb . If you want to specify different keys per environment and per developer you can use the following.


if Rails.env == "production"
  # no production app yet
else
  if ENV['USER'] == 'monica'
    Rails.application.config.middleware.use OmniAuth::Builder do
      provider :twitter, 'CONSUMER_KEY', 'CONSUMER_SECRET'
      provider :facebook, 'APP_ID', 'APP_SECRET'  # Find these values on the Facebook App page
    end
  end
end

Try it out!

Now all you have to do is create a link somewhere in your view

<%= link_to "Log in with Facebook", "/auth/facebook" %>

No need to create a route – it is handled by OmniAuth.

In your application click the “Log in with Facebook” link. You should see the Request for Permission box below.

Facebook Request for Permission

Click agree and assuming you followed Ryan Bates’ tutorial you should see whatever your SessionsController#create action produces.

If you get an error related to the redirect_uri keep on reading.

Invalid redirect_uri: Given URL is not allowed by the Application configuration

{
  "error": {
    "type": "OAuthException",
    "message": "Invalid redirect_uri: Given URL is not allowed by the Application configuration."
  }
}

What this error is saying is that the Site URL that we set up with Facebook does not match where OmniAuth is telling Facebook to take the user after they logged in. So Facebook refuses to perform the redirect.

But how can that be? We set the Site URL to localhost:3000. Where is OmniAuth redirecting the request?


https://graph.facebook.com/oauth/authorize?client_id=123123412395354&redirect_uri=http%3A%2F%2F127.0.0.1%3A3000%2Fauth%2Ffacebook%2Fcallback&scope=email%2Coffline_access&type=web_server

A quick look at the URL reveals the problem: OmniAuth is setting the redirect_uri to 127.0.0.1:3000 instead of localhost:3000. If this happens to you make sure you’re accessing your app on your dev machine through http://localhost:3000 instead of http://127.0.0.1:3000 . OmniAuth will pick up the url you enter in your browser as the application url and use it for the callback.

This article has 12 comments

  1. Monica Olinescu

    Ooooh good question. It’s true the railscast doesn’t cover this.

    Somewhere in your routes file you set up this:

    match ‘/auth/failure’, :to => ‘profiles#failure’

    Now you also need to define the action failure in the controller. Facebook will redirect the user to this url if they entered invalid credentials or some other error occurred.

    class ProfilessController < ApplicationController

    def failure
    redirect_to login_url, :flash => {:error => "Could not log you in. #{params[:message]}"}
    end

    end

  2. Nathan

    Thanks so much for posting this! Exactly what I was looking for. But I got another error you didn’t cover in this post. Any clue what this means?

    OpenSSL::SSL::SSLError

    SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

  3. ceedubU

    Thanks, Monica for a clear explanation. I had the redirect_uri problem, and your solution fixed it!

  4. cgrant

    I run Rails 3 with Passenger in a subfolder off my root hostname. While twitter seems to preserve the proper URI on the callback, Facebook routes to the root hostname throwing an /auth/facebook/callback does not exist.

    I’ve tried setting OmniAuth.config.full_host = ‘http://hostname.com/subdirectory’

    but that throws a NoMethodError (undefined method `to_key’ for :user:Symbol):

    in my Authentications controller.

    Do you know how to properly set the callback URI when running rails in a subdirectory for Facebook?

    Thanks.

  5. SSCirrus

    Hi Monica,

    Your tutorial is one of the very few out there that seem to deal with this topic so thank you!

    Since the launch of Omniauth 1.0 and changes to Facebook apps, Facebook does NOT seem to accept the App Domain `localhost` any more. I have set Site URL to `http://localhost:3000/` but without being able to set app domain all I get back from /auth/facebook is ‘—‘.

    Do you have any pointers on this? Thanks a lot,

    SSCirrus

  6. Swapnil

    I can authorize user access to my app in facebook and twitter. Once user says ‘Allow’/’Authorize’ in respective sites then I am able to get access token for further actions. But if in meantime user disallows to post feeds/tweets on his respective accounts then I my status update fails. How should I check if user is allowing posting feed/tweet then do so else do nothing?

  7. Mark

    Some of my last comment got a little mangled… the localtunnel client sets up an ssh connection to a unique subdomain of localtunnel.com. e.g. –

    $ localtunnel -k ~/.ssh/id_rsa.pub 3000

    will produce something like this:

    Port 3000 is now publicly accessible from http://8bv2.localtunnel.com

  8. Dave Clayton

    A simper solution to the domain problem is to add something like this to your hosts file:

    127.0.0.1 dev.mydomain.com

    Where mydomain.com is the domain you enter in Facebook. This way you can have dev.mydomain.com point to your local machine for development and Facebook will accept it as a valid site as it matches the wildcard *.mydomain.com

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>