Search code examples
ruby-on-rails-3deviseomniauth

Omniauth Facebook Manual Rails Routes


I am trying to use Omniauth facebook with two devise models in a Rails 3 app. Currently that's not something that's possible using omniauthable and the devise helpers.

A similar question answered how to do this:

Omniauth "with" STI and devise

"..move your omniauth configuration from devise.rb to omniauth.rb and create your own omniauth routes.'

But I am having trouble in defining these routes and helpers, i.e. for facebook I used a devise helper like this:

user_omniauth_authorize_path(:facebook) 

..which redirected to facebook and then placed a callback URL I set up in my devise_for scope.

What would my routes/helpers look like for the omniauth-facebook strategy if setting up manually?

I already had omniauth-facebook and devise nicely working for the 'User' model before, so I have the various

@user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user, params[:state])

..parts ready to go, but now with two models. I'm just having trouble with replacing the devise helpers I think.


Solution

  • Your link should look this this:

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

    You also have to create some callback routes, and there are 2 ways you could do this. You can either:

    1. Define a route that catches all callbacks and redirects to a single controller's action:

      get "/auth/:provider/callback" => "authentications#create"
      

      You can then use params[:provider] to get the name of the provider. Using an if you could then do things differently depending on the provider.

    2. Or define a route for every single provider where you can point to different actions in your controller:

      get "/auth/twitter/callback" => "authentications#twitter"
      get "/auth/facebook/callback" => "authentications#facebook"
      

      These routes can also be condensed in a single route:

      get "/auth/:action/callback",
        :to => "authentications",
        :constraints => { :action => /twitter|facebook/ }
      

      You would then need to define these actions. In the twitter action you could fetch the user's tweets and in the facebook action you could fetch the user's posts, for example.

    Also, don't forget to create the failure action to deal with the situation where a user does not authorize logging in with a certain provider.

    Now, you will come across a problem. How do you find out where the link should point to? For Twitter and Facebook, it seems pretty obvious (/auth/twitter and /auth/facebook, respectively).

    But what if you are using the omniauth-google-oauth2 gem to sign in using Google+? Your only hope is that each omniauth gem (listed here) has some good documentation.

    In any case, if you don't know the url you're supposed to use or if you simply don't like the url used by a certain gem, you can always change it!

    For example the url /auth/google_oauth2 is certainly not pretty, at least compared to facebook's and twitter's urls. To change the url, use the name option.

    # omniauth.rb, when using pure omniauth
    provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
      {
        name: 'google'
      }
    
    # devise.rb, when using omniauth+devise
    config.omniauth :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
      {
        name: 'google',
      }
    

    Now you can use the url /auth/google, much better.

    Note: I made several references to an AuthenticationsController but maybe what you have is a CallbacksController or an OmniauthCallbacksController, it doesn't really matter what you call it.