Devise omniauth(oauth) sign_in, and sign_up path setting - ruby-on-rails

I want to separate my oauth redirect paths. One is for facebook and google(register/info1), the other is for twitter(register/info2).
My users go to register/info(1/2) pages, when they sign up first time.
After users sign up and sign in next time, they go to home/main, instead of register/info(1/2)
But after_sign_up_path_for method does not working in omniauth_callback_controller. So, Users always go to register/info(1/2).
Currently, I set my omniauth_callback_controllers.rb like this.
class User::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
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:twitter, :facebook, :google_oauth2].each do |provider|
provides_callback_for provider
end
def after_sign_in_path_for(resource)
auth = request.env['omniauth.auth']
#identity = Identity.find_for_oauth(auth)
#user = User.find(current_user.id)
if #user.persisted?
if #identity.provider == "twitter"
register_info2_path
else
register_info1_path
end
else
home_main_path
end
end
If you have any ideas or related documents, please let me know. Thanks.

you can set the callback path per strategy in the omniauth.rb initializer:
for example:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, "app_id", "password",
scope: 'public_profile', info_fields: 'id,name,link', display: 'popup', callback_path: '/stores/facebook_callback'
end

Related

How to redirect a user signed up with omniauth (Rails with Devise) to a specific page?

Hi I just setup omniauth for Facebook and Google in my app by following this tutorial : http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/
Here's my OmniauthCallbacksController :
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}".gsub(/_/," ").split[0...1].join(' ').capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:google_oauth2, :facebook].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
# def google_oauth2
# raise request.env["omniauth.auth"]
# end
end
I want to redirect all the users who have signed up with facebook or google (Not sign in, sign up for a new account) to their user profile page with a notice asking them to change their username because I set the email as their username on signup. How can I do this?
after this line sign_in_and_redirect #user, event: :authentication
You can add a cookies value that this user is signed up using omniauth.
cookies[:oA] = true
In the after_sign_in_path_for(resource) method check if the value of the cookie is true, add a path username_path(resource) for example.

Devise's after_sign_in_path_for works after signing in normally, but does not work after signing in through Facebook or Twitter. Why is that?

I am working on a rails app right now that allows user's to log in normally, via twitter, and via Facebook as well. I am using devise, omniauth-twitter, and omniauth-facebook.
After signing up/registering, I want to redirect users to the page verify_user_email_path. I have my custom devise RegistrationsController which overrides the standard devise RegistrationsController. It looks like this:
class CustomDeviseControllers::RegistrationsController < Devise::RegistrationsController
def verify_email
flash[:notice] = ""
end
def update_email
#user = User.find(current_user.id)
params[:user].delete(:current_password)
if #user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
flash[:notice] = "Welcome! You have signed up successfully."
sign_in #user, :bypass => true
redirect_to bookshelf_index_url
else
#error_message = "You have entered an invalid email address"
render "verify_email"
end
end
protected
def after_sign_up_path_for(resource)
# I WANT TO REDIRECT USERS HERE AFTER SIGNING UP
verify_user_email_path
end
end
As you can see, after any user signs up, they should be redirected to verify_user_email_path. However/sadly, users are only redirected if they sign up normally. So when users register on my site (they enter in an email, a password, and then confirm their password), after_sign_up_path_for correctly redirects users to verify_user_email_path. If users sign up via Facebook/Twitter, the users are simply redirected to the root_url instead. That is the bug I need to fix.
This is my custom OmniauthCallbacksController (underneath the all caps comment is where I sign users in):
class CustomDeviseControllers::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
# HERE IS WHERE I SIGN USERS IN
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].each do |provider|
provides_callback_for provider
end
end
Aaaand here, is my config/routes.rb:
Rails.application.routes.draw do
devise_for :users, :controllers => {
omniauth_callbacks: 'custom_devise_controllers/omniauth_callbacks',
registrations: 'custom_devise_controllers/registrations' }
devise_scope :user do
get "users/verify_email" => 'custom_devise_controllers/registrations#verify_email', :as => :verify_user_email
post "users/update_email" => 'custom_devise_controllers/registrations#update_email', :as => :update_user_email
end
Instead of using after_sign_up_path_for in my Registrations controller, I use after_sign_in_path_for in the application controller. If the number of sign in attempts equals one, that means the user just signed up.
Here is my application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def after_sign_in_path_for(resource)
if resource.sign_in_count == 1
verify_user_email_path
else
root_url
end
end
end
So now, whenever someone first signs up, they go to verify_user_email_path. If they are logging in any other time, they go to the root_url.
Thanks, everyone!
Your OmniauthCallbacksController doesn't use the method after_sign_up_path_for so obviously you don't get the redirection you want.
Also, that class_eval thing is completely unnecessary. Here's how that controller should look:
class CustomDeviseControllers::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
omniauth = env["omniauth.auth"]
#user = User.from_omniauth(omniauth)
if #user.persisted?
sign_in #user
set_flash_message(:notice, :success, kind: omniauth.provider.capitalize) if is_navigational_format?
redirect_to verify_user_email_path
else
session["devise.#{omniauth.provider}_data"] = omniauth
redirect_to new_user_registration_url
end
end
alias_method :facebook, :all
alias_method :twitter, :all
end

email access using facebook authentication rails

I am unable to access the user email through facebook authentication.
my code in authentication controller
def facebook
omni= request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omni['provider'],omni['uid'])
if authentication
flash[:notice]="Logged in successfully"
sign_in_and_redirect User.find(authentication.user_id)
elsif current_user
token=omni['credentials'].token
token_secret=omni['credentials'].secret
current_user.authentications.create!(:provider=>omni['provider'],:uid=>omni['uid'],:token=>token,:token_secret=>token_secret)
flash[:notice]="Authentication successful."
sign_in_and_redirect current_user
else
user=User.new
# user.email=omni['extra']['raw_info'].email
user.apply_omniauth(omni)
if user.save
flash[:notice]="Logged in."
sign_in_and_redirect User.find(user.id)
else
session[:omniauth]=omni.except('extra')
redirect_to new_user_registration_path
end
end
end
devise.rb
config.omniauth :facebook, 'xxxxxxxxxxxxxxx851','xxxxxxxxxxxxxxxxxxd47aae3', {:scope => ' email,publish_stream,offline_access' ,:display => 'popup'}
in user model
def apply_omniauth(omni)
authentications.build(:provider => omni['provider'],
:uid=>omni['uid'],
:token=>omni['credentials'].token,
:token_secret=>omni['credentials'].secret,
)
x=omni["info"]["name"].split # split the full name into first and last name
self.first_name=x[0]
self.last_name=x[1]
self.profile_name=omni['info']['nickname']
end
Is their something in the code?
Last, I remember, email can be found at omni.info.email.
Also, I advice you to use . notation here, instead of hash.

Omniauth Google Outh 2 Keeps Redirecting To Google?

I have Google Omniauth 2 correctly authorizing, pulling the email, creating the users and logging in.
However, each time I log out and click my "Log In With Google" link - it directs me to the Google Allow Access page and makes me approve it again and then logs me in.
Is this just how google operates? Is there a way to pass a scope to make it not ask each time?
Here is my omniauth initializer
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, '####', '####', :scope => 'email,offline_access', :display => 'popup'
provider :google_oauth2, '####.apps.googleusercontent.com', '#####', { }
end
Here is my sessions controller:
class SessionsController < ApplicationController
def create
auth = request.env["omniauth.auth"]
user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth)
session[:user_id] = user.id
#redirect_to root_url, :notice => "Signed in!"
redirect_back_or user
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Signed out!"
end
end

Devise Omniauth "encrypted_password may not be NULL" for new user

I am using Devise with Omniauth to have users sign into my app with Facebook. I used the Railscast tutorials to get it up and running.
If a user is already a member of my site authenticating through facebook works fine. The problem comes in when authenticating a new user with facebook. When it goes to create a new user for my User model I get the "users.encrypted_password may not be NULL" error. I can't figure out how to pass over the password to the User model from Facebook information.
This is what I have:
authentations_controller.rb
class AuthenticationsController < ApplicationController
def index
#authentications = current_user.authentications if current_user
end
def create
omniauth = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
if authentication
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
else
user = User.new
user.apply_omniauth(omniauth)
if user.save
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omniauth.except('extra')
redirect_to new_user_registration_url
end
end
end
user.rb
def apply_omniauth(omniauth)
self.email = omniauth['user_info']['email'] if email.blank?
authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'])
end
def password_required?
(authentications.empty? || !password.blank?) && super
end
Any help would be great, thanks in advance!
Add :password => Devise.friendly_token[0,20] when creating a new user from facebook omniauth.
I believe Devise is expecting something in the password field to create a User. Since there is no password when doing facebook oauth (not on your app side at least), you just need to create a dummy password as show above.
See this for more info:
https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

Resources