Skip to content

Instantly share code, notes, and snippets.

@PanosJee
Created March 17, 2011 22:58
Show Gist options
  • Save PanosJee/875320 to your computer and use it in GitHub Desktop.
Save PanosJee/875320 to your computer and use it in GitHub Desktop.
Login / Register to Refinery with Omniauth (facebook, twitter, openid, etc)
# Create a role user (no perms). Fire up the console rails c
$> Role.create(:title=>'User')
# In your Gemfile add
gem 'oa-oauth', :require => 'omniauth/oauth'
# At the beginning of devise.rb. You can also create a yaml file and instantiate when Rails begin
# For shake of simplicity I added the credentials at devise.rb
Facebook = Rails.env.development? ? {:app_id => 2621xxx, :secret => 'e81f33d042xxxxx'} :
{:app_id => 1749xxx9, :secret => '13c11be6628dc1xxxx'}
# In devise.rb inside the config block
config.omniauth :facebook, Facebook[:app_id], Facebook[:secret] , {
:scope => "email,offline_access,share_item, status_update, user_birthday"}
# rake refinery:override controller=registrations
# 1. We need to create a username so that we comply with the validation
# After line 15 we may add the following, if we have an email
@user.username = @user.email.split('@')[0]
# By default refinery adds the refinery role when somebody registers.
# We keep this behaviour only for the first user. At line 20 we add:
if !refinery_users_exist?
@user.add_role(:refinery)
@user.plugins = @selected_plugin_titles
else
@user.add_role(:user)
end
# Then at line 55 we modify the redirect? method
# We remove the condition refinery_users_exist?
def redirect?
if refinery_user?
redirect_to admin_users_url
end
end
# We edit routes.rb as following
devise_for :users, :controllers => {
:registrations => "users",
:sessions=>"sessions",
:omniauth_callbacks => "users/omniauth_callbacks"
}, :stateless_token => false
match "/registrations/auth/facebook" => redirect("/users/auth/facebook")
# We add somewhere in our views the Login with Facebook button
<%= url_for users_auth_facebook_path(:facebook) %>
# We then create the controller users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model
@user = User.find_for_facebook_oauth(env["omniauth.auth"], current_user)
if @user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook"
sign_in_and_redirect @user, :event => :authentication
else
session["devise.facebook_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
# And finally we add the following method to user.rb
# Of course the Facebookdata contains different data according to the permissions
# we set at devise.rb (omniauth config).
# Do not forget we need a password for devise (so we create a random one) and a
# a password. We also need to store the Facebook token if we need offline access
# If you ask for more user data then you should modify your user table accordingly
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token['extra']['user_hash']
if user = User.find_by_email(data["email"])
user
else # Create an user with a stub password.
user = User.new(:email => data["email"], :password => Devise.friendly_token[0,20],
:username => data['name'], :first_name=>data['first_name'],
:last_name=>data['last_name'],:birthday => data['birthday'],
:gender => data['gender'], :uid => data['id'],
:token => access_token['credentials']['token'])
user.add_role(:user)
user.save!
end
end
# For this example we create the following migration
class AddFieldsToUser < ActiveRecord::Migration
def self.up
add_column :users, :uid, :bigint, :limit => 30
add_column :users, :token, :text
add_column :users, :first_name, :string
add_column :users, :last_name, :string
add_column :users, :birthday, :date
add_column :users, :gender, :string, :limit => 15
remove_column :users, :password_salt
end
def self.down
remove_column :users, :uid
remove_column :users, :token
remove_column :users, :first_name
remove_column :users, :last_name
remove_column :users, :birthday
remove_column :users, :gender
add_column :users, :password_salt
end
end
@PanosJee
Copy link
Author

I have written the code about 2 months back so I do not fully remember. If you encounter any bugs please fork away and fix it.
Thanks

@freemarmoset
Copy link

Thank you very much for putting that together. This is pretty close to what I have. For some reason there is no route matching "/users/auth/facebook". That falls through to refinery's default pages route. Don't know if that is something you ran across when you were first implementing or not? Any insight there? I'll keep plugging at it and let you know what I find. Thanks again.

@PanosJee
Copy link
Author

PanosJee commented Mar 17, 2011 via email

@freemarmoset
Copy link

I did create the users/ominiauth_...callbacks and setup devise.rb

config.omniauth :facebook, Facebook[:app_id], Facebook[:secret]

wasn't worried about scope for my case. The callback route is recognized. It's the initial login /users/auth/facebook is what isn't picked up for some reason.

@jcmendez
Copy link

@omeryavuz
Copy link

registrations changed users so you must run this command
rake refinery:override controller=users

@omeryavuz
Copy link

Also you must change following items
for user login
<%= url_for users_auth_facebook_path(:facebook) %>

on routes.rb

devise_for :users, :controllers => {
:registrations => "users",
:sessions=>"sessions",
:omniauth_callbacks => "users/omniauth_callbacks"
}, :stateless_token => false

match "/users/auth/facebook" => redirect("/users/auth/facebook")

Thanks for your effort.

@PanosJee
Copy link
Author

PanosJee commented Jun 13, 2011 via email

@dennismonsewicz
Copy link

After adding in @omeryavuz latest code I am getting nasty redirect loop issues... anyway of fixing this?

Link:

<%= link_to "Sign in with Olympus", users_auth_olympus_path %>

Routes.rb:
devise_for :users, :controllers => {
:registrations => "users",
:sessions=>"sessions",
:omniauth_callbacks => "users/omniauth_callbacks"
}, :stateless_token => false

devise_scope :users do
match "/users/auth/olympus" => redirect("/users/auth/olympus")
end

Olympus is the name of a 3rd party oauth system I have built

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment