Skip to Content
Course content

130: OmniAuth for Social Login

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I remember a junior dev I worked with a few years back who spent an entire weekend trying to build a custom "Login with GitHub" feature from scratch. He was manually crafting redirect URLs, wrestling with client_id and client_secret exchanges, and losing his mind over the state parameter for security. He came to me on Monday morning looking completely defeated. I told him, "Why are you doing the hard work when OmniAuth already did it for us?"

The reality is that OAuth2 is a beast. Every provider—Google, GitHub, Facebook, Twitter—implements it slightly differently. If you try to write your own integration for each one, you'll end up with a codebase full of repetitive, fragile HTTP requests. OmniAuth solves this by acting as a standardized Rack middleware. It abstracts the complexity of the "handshake" into a single interface, allowing you to plug in "strategies" for different providers without changing how your app handles the resulting user data.

Connecting the Middleware and Strategies

OmniAuth isn't a monolithic library; it's a framework for strategies. To get it working, you first install the omniauth gem, and then you install the specific strategy gem for the provider you want—for example, omniauth-github. This keeps your application lean because you aren't loading code for Facebook if you only intend to use GitHub.

In a typical Ruby on Rails app, you'll set this up in an initializer. You tell OmniAuth which provider to use and provide the credentials you got from the provider's developer console. It looks something like this:

OmniAuth.config.allowed_request_methods = [:post]

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], scope: "user:email"
end

Notice how we use environment variables for the keys. Never, ever hardcode these into your version control. I've seen too many production apps compromised because a developer pushed their client_secret to a public GitHub repo. Once this is configured, OmniAuth automatically intercepts any request to /auth/github and redirects the user to GitHub's authorization page. You don't even have to write a controller action for the initial request.

Taming the OmniAuth Auth Hash

Once the user grants permission on the provider's site, they are sent back to your application via a callback URL (usually /auth/github/callback). This is where the magic happens. OmniAuth takes the complex response from the provider and normalizes it into a consistent Ruby hash called the auth hash, which is available in request.env['omniauth.auth'].

The brilliance of this approach is that regardless of whether the user logged in via GitHub or Google, the structure of this hash remains largely the same. You'll find the user's unique ID under uid and their profile details under info. Here is how I usually handle the callback in a controller:

def github
  auth = request.env['omniauth.auth']
  user = User.find_or_create_by(provider: auth['provider'], uid: auth['uid']) do |u|
    u.name = auth['info']['name']
    u.email = auth['info']['email']
    u.image = auth['info']['image']
  end
  
  session[:user_id] = user.id
  redirect_to root_path, notice: "Successfully logged in via GitHub!"
end

By using find_or_create_by, you ensure that returning users are simply logged in, while new users are seamlessly registered. You've effectively bypassed the need for a sign-up form, password confirmation emails, and password hashing—all handled by the provider.




📋 Practical Task

Exercise: Building a GitHub-powered User Session Manager

Your goal is to integrate GitHub social login into an existing Ruby on Rails application. You will need to configure the middleware and implement the logic to persist the user in the database.

  • Configuration: Add the omniauth and omniauth-github gems to your Gemfile. Create an initializer at config/initializers/omniauth.rb and configure the GitHub provider using environment variables for the GITHUB_KEY and GITHUB_SECRET.
  • Routing: Map the callback route get '/auth/:provider/callback', to: 'sessions#create' in your routes.rb file.
  • Logic: In the SessionsController#create action, extract the auth hash from request.env['omniauth.auth']. Implement a mechanism to find an existing user by their uid and provider, or create a new User record if they don't exist, saving their name and email from the info block of the hash.
  • Session Management: Store the resulting user's ID in the session[] hash and redirect the user to a dashboard page with a success message.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.