Skip to content

Instantly share code, notes, and snippets.

@ssuprunenko
Last active March 23, 2020 04:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ssuprunenko/7923d80f73c046a70a1d to your computer and use it in GitHub Desktop.
Save ssuprunenko/7923d80f73c046a70a1d to your computer and use it in GitHub Desktop.
Rails 4, Devise, Omniauth (with multiple providers)
class CreateIdentities < ActiveRecord::Migration
def change
create_table :identities do |t|
t.string :provider
t.string :uid
t.integer :user_id
t.timestamps null: false
end
add_index :identities, :user_id
end
end
/ app/views/layouts/_login_form.html.slim
/ with 'font-awesome-sass' gem
= link_to user_omniauth_authorize_path(:google), class: 'btn btn-block btn-social btn-google-plus' do
= icon 'google-plus', 'Sign in with Google', class: 'fa-fw'
= link_to user_omniauth_authorize_path(:linkedin), class: 'btn btn-block btn-social btn-linkedin' do
= icon 'linkedin', 'Sign in with LinkedIn', class: 'fa-fw'
# config/initializers/devise.rb
Devise.setup do |config|
# ...
config.omniauth :google_oauth2,
ENV['GOOGLE_CLIENT_ID'],
ENV['GOOGLE_CLIENT_SECRET'],
name: 'google'
config.omniauth :linkedin,
ENV['LINKEDIN_KEY'],
ENV['LINKEDIN_SECRET'],
scope: 'r_basicprofile r_emailaddress',
secure_image_url: true
# ...
end
source 'https://rubygems.org'
gem 'rails', '4.2.1'
gem 'devise'
gem 'omniauth-linkedin-oauth2'
gem 'omniauth-google-oauth2'
# == Schema Information
#
# Table name: identities
#
# id :integer not null, primary key
# provider :string
# uid :string
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Identity < ActiveRecord::Base
belongs_to :user
validates :provider, :user_id, :uid, presence: true
def self.find_from_omniauth(auth)
find_by(provider: auth.provider, uid: auth.uid)
end
def self.create_from_omniauth(auth, user)
Identity.create!(user: user, provider: auth.provider, uid: auth.uid)
end
end
# app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_filter :authenticate_user!
%w(google linkedin).each do |provider|
define_method provider do
auth = request.env['omniauth.auth']
unless identity = Identity.find_from_omniauth(auth)
user = User.from_omniauth(auth)
identity = Identity.create_from_omniauth(auth, user)
end
if identity.user.persisted?
flash[:success] = 'Signed in successfully.'
sign_in_and_redirect identity.user
else
redirect_to new_user_registration_url
end
end
end
def failure
redirect_to root_path
end
end
Rails.application.routes.draw do
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
end
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# name :string
# email :string default(""), not null
# encrypted_password :string default(""), not null
# reset_password_token :string
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0), not null
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :inet
# last_sign_in_ip :inet
# created_at :datetime
# updated_at :datetime
#
class User < ActiveRecord::Base
devise :database_authenticatable,
:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:omniauthable, omniauth_providers: [:google, :linkedin]
has_many :identities
def self.from_omniauth(auth)
where(email: auth.info.email).first_or_create do |user|
user.name = auth.info.name
user.password = Devise.friendly_token[0,20]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment