DEV Community

Cover image for Omniauth without Devise
Yaroslav Shmarov
Yaroslav Shmarov

Posted on • Originally published at blog.corsego.com on

Omniauth without Devise

Previously I’ve covered Github omniauth with Devise, and Github omniauth with Devise without email registration.

An even simpler solution would be to sign in via a social login provider without Devise at all! Here’s the easiest way to do it.

First, add the omniauth gems:

# Gemfile
gem 'omniauth-github', github: 'omniauth/omniauth-github', branch: 'master'
gem "omniauth-rails_csrf_protection", "~> 1.0"
Enter fullscreen mode Exit fullscreen mode

Add your social provider API credentials:

# https://github.com/omniauth/omniauth
# https://github.com/settings/applications/new
# echo > config/initializers/omniauth.rb
# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :github, "GITHUB_ID", "GITHUB_SECRET"
end
Enter fullscreen mode Exit fullscreen mode

Create a user model. We will also add a few static pages:

  • /landing_page that can be accessed without authentication
  • /dashboard that requires authentication
rails g controller static_pages landing_page dashboard
rails g model User email github_uid
Enter fullscreen mode Exit fullscreen mode

Routes:

# config/routes.rb
  root 'static_pages#landing_page'
  get 'dashboard', to: 'static_pages#dashboard'

  get 'auth/github/callback', to: 'sessions#create'
  delete 'logout', to: 'sessions#destroy'
  # get 'login', to: redirect('/auth/github'), as: 'login'
Enter fullscreen mode Exit fullscreen mode

Gems like devise provide some default methods, that we will have to add on our own now:

  • def current_user - get the current user from session params.
  • def user_signed_in? - check if there is a current user.
  • def require_authentication - to restrict controller actions for non-authenticated users.
  • helper_method :current_user - to make current_user available in views.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  helper_method :current_user

  def require_authentication
    redirect_to root_path, alert: 'Requires authentication' unless user_signed_in?
  end

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  def user_signed_in?
    # converts current_user to a boolean by negating the negation
    !!current_user
  end
end
Enter fullscreen mode Exit fullscreen mode

The button to /auth/github will redirect to the github login page.

# app/views/layouts/application.html.erb
<%= link_to 'Home', root_path %>
<% if current_user %>
  <%= current_user.email %>
  <%= link_to 'Dashboard', dashboard_path %>
  <%= button_to 'Logout', logout_path, method: :delete, data: { turbo: false } %>
<% else %>
  <%= button_to "Sign in with Github", "/auth/github", data: { turbo: false } %>
<% end %>
Enter fullscreen mode Exit fullscreen mode

After successful authentication, the user should be redirected to sessions#create with request.env['omniauth.auth'].

# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def create
    @user = User.from_omniauth(request.env['omniauth.auth'])
    if @user.persisted?
      session[:user_id] = @user.id
      redirect_to dashboard_path, notice: "Logged in as #{@user.email}"
    else
      redirect_to root_url, alert: 'Failure'
    end
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
end
Enter fullscreen mode Exit fullscreen mode

from_omniauth will find the users email and uid in the data provided by github, and find or create the user.

# app/models/user.rb
class User < ApplicationRecord
  validates :github_uid, presence: true, uniqueness: true
  validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }, presence: true, uniqueness: true

  def self.from_omniauth(access_token)
    github_uid = access_token.uid
    data = access_token.info
    email = data['email']

    User.find_or_create_by(email:, github_uid:)
  end
end
Enter fullscreen mode Exit fullscreen mode

Finally, require authentication to visit /dashboard:

# app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
  before_action :require_authentication, only: :dashboard

  def landing_page
  end

  def dashboard
  end
end
Enter fullscreen mode Exit fullscreen mode

That’s it! Now you can use omniauth without devise!

Top comments (4)

Collapse
 
ahmednadar profile image
Ahmed Nadar

Nice article as usual.
I have noticed many apps are using different authanitcation way these days.
Do you think Rails apps should implement authanitcations without Devise

Collapse
 
superails profile image
Yaroslav Shmarov

It really depends on what you are building. For many cases omniauth-only would be enough.

Sometimes, getting a confirmed email address can be much more valuable, than having an omniauth user account.

I think that devise via email/password + omniauth still stays the most versatile approach.

Collapse
 
idd profile image
Ivo Di

After trying an official omniauth and devise and omniauth-google-oauth2 docs i couldn't make it all working. But thanks for your article I finally did what I wanted.
❤️

Collapse
 
superails profile image
Yaroslav Shmarov

wow, I'm glad it helped you!