Setting up OmniAuth 2.0 in rails
Published: 2021-04-18 17:00:09

I just finished my rails project for flatiron school. The overall project was fun to do and I learned a ton about rails in a week or so. The hardest part about the project was incorporating a third party authentication to my application. In my case I wanted to sign in through facebook. However, I ran into problems with omniauth saying that I was using an older version. The problem for that was because a newer version of omniauth came out and required additional configuration to get it up and running. The steps to setup third party authentication through Omniauth is by doing the following...

First, we need to add a few gems to our gemfile.
```ruby
gem "thin", "~> 1.8"
gem "omniauth-facebook", "~> 8.0"
gem "omniauth-rails_csrf_protection", "~> 1.0"
```

The most important gem here for omniauth to work is that last one. This is because there were some security issues and in order to deal with those, we need to add the csrf_protection gem to our gemfile. Now in my case I am just doing facebook but if you wanted to authenticate through other strategies like github, you would need to add gem "omniauth-github" to the gemfile.

The next step is to tell the Omniauth builder what providers we are using and setup each providers api-key and app-secrets. In the case of facebook, you would find these in the facebook developer page. To set this all up we will need to create a new file called omniauth.rb in our initializers folder. Inside that file we will need to add the following code...

```ruby 
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET']
end
```

Here all we are doing is telling omniauth builder what providers we are using by supplying each providers app-id-key and app-secret.

Once that is all setup we will now need to create a new route for the callback. In my application this route looks like this...

```ruby
get "/auth/facebook/callback", to: "omniauth_callbacks#facebook"
```

Essentially what this is doing is after we sign in with facebook we are redirected to this url which will then call a action called facebook. In my application, I created a new controller called omniauth_callbacks_controller.rb which I implemented the following code.

```ruby
class OmniauthCallbacksController < ApplicationController

  def facebook
    user = User.find_or_create_by(uid: auth[:uid], provider: auth[:provider])
    if user
      user.password = "facebook_auth"
      session[:user_id] = user.id
      user.save
      redirect_to user_portfolios_path(user)
    end
  end

  def auth
    request.env['omniauth.auth']
  end

end
```
What all this code is doing is essentially fetching my facebook information when I signed in through facebook and creating a new user in my users table using that information. Something important to note is in order to fetch all that user information we need to create a method called auth. The request.env['omniauth.auth'] is how omniauth fetched all the user information when logging in with facebook under the hood. 

If you look at the hash that this method returns you will see that there are some attributes, we need to add to our users table. Thus, I needed to create a new migration to add the provider and the uid to my user table. What the facebook action is doing is its finding or creating a user by the uid that is being passed in and setting the session[:user_id] to the id of the users account matching the uid. Then it is redirecting the user to the main page.

Now in order to actually setup a button that sends us through the authentication process we will need to add a button like this...

```ruby
<%= button_to "Sign in with Facebook", "/auth/facebook", method: :post, id: "fb-btn" %>
```

Important things to note about the button. With the newer version of omniauth, for security reasons it no longer uses get requests so in our button we need to explicitly tell it to make a post request which will then allow us to start the authentication process for facebook.