OmniAuth is NOT a scary Monster

Breaking Down OmniAuth, an OAuth library for Ruby

Ali Schlereth
3 min readMar 22, 2017

As a new Developer, I had little trouble understanding the concept of OAuth, and how to hand-roll a version or two. When it came to OmniAuth though, it was hard to grasp what was going on, where, and how. And, to track the patterns I was seeing across OmniAuth gems.

OmniAuth

OAuth

OAuth, or Open Authorization is a protocol for users to authorize websites to access their information without handing over a password.

If you are hand-rolling OAuth, the basic flow looks something like this:

  1. Application is registered with intended provider(i.e. Google, Facebook, GitHub, etc) and a client_id and client_secret are obtained
  2. Application sends out a request to the provider (i.e. Google, Facebook, GitHub, etc) including the application’s client_id and client_secret
  3. Provider asks the user if they’d like to authorize the application to access their personal info
  4. If yes, the provider sends back a token/code to ‘/auth/:provider/callback’, a route found in the application
  5. The application sends out a 2nd request to the provider with the token/code
  6. The provider sends a response back with a user’s information
  7. The application parses the response to create a hash of user info

OmniAuth

There are many steps in the above process, which is why OmniAuth is around. There are many gems out there which implement OmniAuth for their application (i.e. omniauth-google-oauth2, omniauth-facebook, omniauth-github); however, it is helpful to understand that they all implement the same basic OmniAuth structures.

The setup for OmniAuth looks something like this.

  1. Register your application with intended provider(i.e. Google, Facebook, GitHub, etc) and obtain your client_id and client_secret
  2. In config/initializers/omniauth.rb you’ll put the following do/end block
Rails.application.config.middleware.use OmniAuth::Builder doend 

Within that block, you will tell OmniAuth which provider to work with.

provider :provider_name, ENV['PROVIDER_ID'], ENV['PROVIDER_SECRET']

Put together it looks something like this:

Rails.application.config.middleware.use OmniAuth::Builder do

provider :github, ENV['GITHUB_ID'], ENV['GITHUB_SECRET']
end

Your provider may also want a hash with scoping options, which might look like this:

Rails.application.config.middleware.use OmniAuth::Builder do  
provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"],
ENV["GOOGLE_CLIENT_SECRET"],
{ :name => "google",
:scope => ['contacts', 'plus.login', 'plus.me', 'email',
'profile'],
:prompt => "select_account",
:image_aspect_ratio => "square",
:image_size => 50,
:access_type => 'offline' }
end

3. Within routes.rb

get 'auth/provider_name', as: 'provider_name_login'
get '/auth/:provider/callback', to: 'sessions#create'

4. Wherever you want your login link to live, it will look something like this:

<=% link_to "Login", provider_name_login_path %>

When the user clicks this link they will be redirected to the provider who will ask for permission to send the application the users’ info. Assuming the user says yes, here is where OmniAuth diverges from general OAuth.

OmniAuth takes care of steps 2–6 from above and provides the following in your ‘sessions#create’

def create   user_info = request.env['omniauth.auth']
..find_or_create_by user using user_info as you see fit..
end

This request.env[‘omniauth.auth’] is a hash of user information sent back from the provider.

If you’re curious about how request.env[‘omniauth.auth’] gets created, the OmniAuth docs say “OmniAuth simply sets a special hash called the Authentication Hash on the Rack environment of a request to /auth/:provider/callback.” and read this StackOverflow thread which provides some more explicit background info.

That’s it?!?

When I first started using OmniAuth, it seemed like a big scary complicated monster. However, once I dug into the patterns involved, there really isn’t much there. It almost seems “too easy.” As long as you understand what it’s doing in the background though, by all means do “easy!”

--

--