Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Setup for Devise + Omniauth

View 01. Gemfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14
gem 'pg'
group :development do
gem 'ruby-debug'
end
gem 'rake', '~> 0.8.7'
gem 'devise'
gem 'oa-oauth', :require => 'omniauth/oauth'
gem 'omniauth'
gem 'haml'
gem 'dynamic_form'
gem 'sass'
gem 'jquery-rails'
gem 'cancan'
gem 'uuidtools'
View 01. Gemfile
1 2 3 4
rails generate devise:install
rails generate devise user
rails g migration add_name_to_users name:string
rails g model authorization provider:string uid:string user_id:integer token:string secret:string name:string link:string
View 01. Gemfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
# /db/migrate/<timestamp>_devise_create_users.rb
 
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
t.encryptable
t.confirmable
t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both
t.token_authenticatable
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
add_index :users, :confirmation_token, :unique => true
add_index :users, :unlock_token, :unique => true
add_index :users, :authentication_token, :unique => true
end
 
def self.down
drop_table :users
end
end
View 01. Gemfile
1 2 3 4 5 6 7
# app/models/authorization.rb
 
class Authorization < ActiveRecord::Base
belongs_to :user
end
View 01. Gemfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# config/environments
 
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
HOST = 'localhost:3000'
ADMIN_EMAIL_FROM = ""
PONY_VIA_OPTIONS = {
:address => 'smtp.gmail.com',
:port => '587',
:enable_starttls_auto => true,
:user_name => '',
:password => '',
:authentication => :plain,
:domain => "localhost.localdomain" }
View 01. Gemfile
1 2 3 4 5 6 7 8 9 10 11
# app/config/initializers/devise.rb
 
Devise.setup do |config|
...
config.sign_out_via = :get
...
config.omniauth :facebook, "KEY", "SECRET"
config.omniauth :twitter, "KEY", "SECRET"
config.omniauth :linked_in, "KEY", "SECRET"
...
end
View 01. Gemfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
require 'uuidtools'
def facebook
oauthorize "Facebook"
end
def twitter
oauthorize "Twitter"
end
def linked_in
oauthorize "LinkedIn"
end
def passthru
render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
end
private
 
def oauthorize(kind)
@user = find_for_ouath(kind, env["omniauth.auth"], current_user)
if @user
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => kind
session["devise.#{kind.downcase}_data"] = env["omniauth.auth"]
sign_in_and_redirect @user, :event => :authentication
end
end
 
def find_for_ouath(provider, access_token, resource=nil)
user, email, name, uid, auth_attr = nil, nil, nil, {}
case provider
when "Facebook"
uid = access_token['uid']
email = access_token['extra']['user_hash']['email']
auth_attr = { :uid => uid, :token => access_token['credentials']['token'], :secret => nil, :name => access_token['extra']['user_hash']['name'], :link => access_token['extra']['user_hash']['link'] }
when "Twitter"
uid = access_token['extra']['user_hash']['id']
name = access_token['user_info']['name']
auth_attr = { :uid => uid, :token => access_token['credentials']['token'], :secret => access_token['credentials']['secret'], :name => name, :link => "http://twitter.com/#{name}" }
when 'LinkedIn'
uid = access_token['uid']
name = access_token['user_info']['name']
auth_attr = { :uid => uid, :token => access_token['credentials']['token'], :secret => access_token['credentials']['secret'], :name => name, :link => access_token['user_info']['public_profile_url'] }
else
raise 'Provider #{provider} not handled'
end
if resource.nil?
if email
user = find_for_oauth_by_email(email, resource)
elsif uid && name
user = find_for_oauth_by_uid(uid, resource)
if user.nil?
user = find_for_oauth_by_name(name, resource)
end
end
else
user = resource
end
auth = user.authorizations.find_by_provider(provider)
if auth.nil?
auth = user.authorizations.build(:provider => provider)
user.authorizations << auth
end
auth.update_attributes auth_attr
return user
end
 
def find_for_oauth_by_uid(uid, resource=nil)
user = nil
if auth = Authorization.find_by_uid(uid.to_s)
user = auth.user
end
return user
end
 
def find_for_oauth_by_email(email, resource=nil)
if user = User.find_by_email(email)
user
else
user = User.new(:email => email, :password => Devise.friendly_token[0,20])
user.save
end
return user
end
def find_for_oauth_by_name(name, resource=nil)
if user = User.find_by_name(name)
user
else
user = User.new(:name => name, :password => Devise.friendly_token[0,20], :email => "#{UUIDTools::UUID.random_create}@host")
user.save false
end
return user
end
 
end
View 01. Gemfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
class RegistrationsController < Devise::RegistrationsController
 
def update
if params[resource_name][:password].blank?
params[resource_name].delete(:password)
params[resource_name].delete(:password_confirmation) if params[resource_name][:password_confirmation].blank?
end
# Override Devise to use update_attributes instead of update_with_password.
# This is the only change we make.
if resource.update_attributes(params[resource_name])
set_flash_message :notice, :updated
# Line below required if using Devise >= 1.2.0
sign_in resource_name, resource, :bypass => true
redirect_to after_update_path_for(resource)
else
clean_up_passwords(resource)
render_with_scope :edit
end
end
end
View 01. Gemfile
1
devise_for :users, :path => "accounts", :controllers => { :omniauth_callbacks => "users/omniauth_callbacks", :registrations => "registrations" }
View 01. Gemfile
1 2 3 4 5 6 7 8 9
# app/models/user.rb
 
class User < ActiveRecord::Base
 
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable
attr_accessible :email, :name, :password, :password_confirmation, :remember_me
has_many :authorizations, :dependent => :destroy
 
end

I searched long and hard for a good multi-provider example of Devise with Omniauth (using Devise's omniauthable). Great to have finally found one.!!

Owner

If you try this code in rails 3.1 you need to change file omniauth_callbacks_controller.rb line 95 from

user.save false

to

user.save :validate => false

Very awesome. Quick tip - as of now you'll need to specify the omniauth gem version explicitly as the 1.0 is incompatible with devise at the moment.

gem 'omniauth', '0.3.2'

See https://github.com/intridea/omniauth/issues/496 for more info.

Also FWIW :lockable is in the migration but not on the User model.

This is for omniauth with version < 1.0. For those of you who wants to use new omniauth 1.0 with devise, follow strategies on

https://github.com/intridea/omniauth/wiki/List-of-Strategies

Line 27: session["devise.#{kind.downcase}_data"] = env["omniauth.auth"]
Line 28: sign_in_and_redirect @user, :event => :authentication

Line 27 should go after Line 28, because Devise resets the session when the user is signed in.

The migration provided here won't work on Devise 2.0+. See https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style for details on how to upgrade. I think this tut might be a little outdated from the get-go.

user.rb:5 needs also to have :omniauth_providers => [:facebook, :twitter, :gplus] and etc. in the devise line in the model.

Do you really want rememberable and database_authenticatable? do those make sense to use with omniauth?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.