Created
June 10, 2014 20:28
-
-
Save geordee/442313484af8b1d61120 to your computer and use it in GitHub Desktop.
Rails 4 OmniAuth using Devise with Twitter, Facebook and Linkedin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Devise.setup do |config| | |
... | |
config.omniauth :facebook, "KEY", "SECRET" | |
config.omniauth :twitter, "KEY", "SECRET" | |
config.omniauth :linked_in, "KEY", "SECRET" | |
... | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ApplicationController < ActionController::Base | |
... | |
def ensure_signup_complete | |
# Ensure we don't go into an infinite loop | |
return if action_name == 'finish_signup' | |
# Redirect to the 'finish_signup' page if the user | |
# email hasn't been verified yet | |
if current_user && !current_user.email_verified? | |
redirect_to finish_signup_path(current_user) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class OmniauthCallbacksController < Devise::OmniauthCallbacksController | |
def self.provides_callback_for(provider) | |
class_eval %Q{ | |
def #{provider} | |
@user = User.find_for_oauth(env["omniauth.auth"], current_user) | |
if @user.persisted? | |
sign_in_and_redirect @user, event: :authentication | |
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format? | |
else | |
session["devise.#{provider}_data"] = env["omniauth.auth"] | |
redirect_to new_user_registration_url | |
end | |
end | |
} | |
end | |
[:twitter, :facebook, :linked_in].each do |provider| | |
provides_callback_for provider | |
end | |
def after_sign_in_path_for(resource) | |
if resource.email_verified? | |
super resource | |
else | |
finish_signup_path(resource) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UsersController < ApplicationController | |
before_action :set_user, :finish_signup | |
... | |
def finish_signup | |
if request.patch? && params[:user] #&& params[:user][:email] | |
if current_user.update(user_params) | |
current_user.skip_reconfirmation! | |
sign_in(current_user, :bypass => true) | |
redirect_to current_user, notice: 'Your profile was successfully updated.' | |
else | |
@show_errors = true | |
end | |
end | |
end | |
private | |
def set_user | |
@user = User.find(params[:id]) | |
end | |
def user_params | |
accessible = [ :name, :email ] # extend with your own params | |
accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank? | |
params.require(:user).permit(accessible) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Identity < ActiveRecord::Base | |
belongs_to :user | |
validates_presence_of :uid, :provider | |
validates_uniqueness_of :uid, :scope => :provider | |
def self.find_for_oauth(auth) | |
identity = find_by(provider: auth.provider, uid: auth.uid) | |
identity = create(uid: auth.uid, provider: auth.provider) if identity.nil? | |
identity | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
TEMP_EMAIL_PREFIX = 'change@me' | |
TEMP_EMAIL_REGEX = /\Achange@me/ | |
# Include default devise modules. Others available are: | |
# :lockable, :timeoutable | |
devise :database_authenticatable, :registerable, :confirmable, | |
:recoverable, :rememberable, :trackable, :validatable, :omniauthable | |
validates_format_of :email, :without => TEMP_EMAIL_REGEX, on: :update | |
def self.find_for_oauth(auth, signed_in_resource = nil) | |
# Get the identity and user if they exist | |
identity = Identity.find_for_oauth(auth) | |
# If a signed_in_resource is provided it always overrides the existing user | |
# to prevent the identity being locked with accidentally created accounts. | |
# Note that this may leave zombie accounts (with no associated identity) which | |
# can be cleaned up at a later date. | |
user = signed_in_resource ? signed_in_resource : identity.user | |
# Create the user if needed | |
if user.nil? | |
# Get the existing user by email if the provider gives us a verified email. | |
# If no verified email was provided we assign a temporary email and ask the | |
# user to verify it on the next step via UsersController.finish_signup | |
email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email) | |
email = auth.info.email if email_is_verified | |
user = User.where(:email => email).first if email | |
# Create the user if it's a new registration | |
if user.nil? | |
user = User.new( | |
name: auth.extra.raw_info.name, | |
#username: auth.info.nickname || auth.uid, | |
email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com", | |
password: Devise.friendly_token[0,20] | |
) | |
user.skip_confirmation! | |
user.save! | |
end | |
end | |
# Associate the identity with the user if needed | |
if identity.user != user | |
identity.user = user | |
identity.save! | |
end | |
user | |
end | |
def email_verified? | |
self.email && self.email !~ TEMP_EMAIL_REGEX | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="add-email" class="container"> | |
<h1>Add Email</h1> | |
<%= form_for(current_user, :as => 'user', :url => finish_signup_path(current_user), :html => { role: 'form'}) do |f| %> | |
<% if @show_errors && current_user.errors.any? %> | |
<div id="error_explanation"> | |
<% current_user.errors.full_messages.each do |msg| %> | |
<%= msg %><br> | |
<% end %> | |
</div> | |
<% end %> | |
<div class="form-group"> | |
<%= f.label :email %> | |
<div class="controls"> | |
<%= f.text_field :email, :autofocus => true, :value => '', class: 'form-control input-lg', placeholder: 'Example: [email protected]' %> | |
<p class="help-block">Please confirm your email address. No spam.</p> | |
</div> | |
</div> | |
<div class="actions"> | |
<%= f.submit 'Continue', :class => 'btn btn-primary' %> | |
</div> | |
<% end %> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
config.action_mailer.delivery_method = :smtp | |
config.action_mailer.perform_deliveries = true | |
config.action_mailer.default_url_options = { :host => config.app_domain } | |
config.action_mailer.smtp_settings = { | |
address: 'smtp.gmail.com', | |
port: '587', | |
enable_starttls_auto: true, | |
user_name: 'someuser', | |
password: 'somepass', | |
authentication => :plain, | |
domain => 'somedomain.com' | |
} | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
devise_for :users, :controllers => { omniauth_callbacks: 'omniauth_callbacks' } | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
match '/profile/:id/finish_signup' => 'users#finish_signup', via: [:get, :patch], :as => :finish_signup | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gem 'devise' | |
gem 'omniauth' | |
gem 'omniauth-twitter' | |
gem 'omniauth-facebook' | |
gem 'omniauth-linkedin' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rails generate devise:install | |
rails generate devise user | |
rails g migration add_name_to_users name:string | |
rails g model identity user:references provider:string uid:string | |
# Modify the db/migrate/[timestamp]_add_devise_to_users.rb to configure the Devise modules you will use. | |
# We usually enable the "confirmable" module when enabling email signups. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/