Skip to content

@schleg /01. Gemfile
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Setup for Devise + Omniauth
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'
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
# /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
# app/models/authorization.rb
class Authorization < ActiveRecord::Base
belongs_to :user
end
# 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" }
# 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
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
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
devise_for :users, :path => "accounts", :controllers => { :omniauth_callbacks => "users/omniauth_callbacks", :registrations => "registrations" }
# 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
@seanaedmiston

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.!!

@schleg
Owner
@ovargas27

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
@dzello

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 intridea/omniauth#496 for more info.

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

@cielo

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

@jimjh

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.

@colindean

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.

@colindean

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

@benjiwheeler

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.