I'm trying to integrate Devise with Omniauth and have some troubles with them both. The main problem is to bind Devise User model with Omniauth authentications. I want a simple way to associate my user, with external providers like facebook, twitter, g+ and so on.
One of the most annoying issues that arise with my application is:
If an user registered on my site with devise (I call it local user), that means, provided an email and a password, when user tries to login with twitter, the system asks for mail confirmation. If that mail already exists, then user have to provide another mail. I want instead that he can confirm with a password that it is actually his email. How to do that? How can I override that template?
This is my authentications controller:
class AuthenticationsController < ApplicationController
def index
#authentications = Authentication.all
end
def create
#authentication = Authentication.new(params[:authentication])
if #authentication.save
redirect_to authentications_url, :notice => "Successfully created authentication."
else
render :action => 'new'
end
end
def destroy
#authentication = Authentication.find(params[:id])
#authentication.destroy
redirect_to authentications_url, :notice => "Successfully destroyed authentication."
end
def twitter
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.apply_omniauth(omni)
if user.save
flash[:notice] = "Logged in."
sign_in_and_redirect User.find(user.id)
else
session[:omniauth] = omni.except('extra')
p session
redirect_to new_user_registration_path
end
end
end
end
I also have no idea where new_users_registration_path is.
Related
I use Sorcery gem in my Rails app. Oauth authentication is working on Google and Github services. But if user has same emails to login to Google and Github, my application ignores other attempt to login, because the used email already stored in database.
So, I need multiple login in my app through Oauth, even if emails in different services is equal. What should I do?
You can do it like this:
put it in ./app/controller/oauths_controller.rb
def callback
provider = auth_params[:provider]
if #user = login_from(provider)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
else
begin
#user = create_from(provider)
reset_session # protect from session fixation attack
auto_login(#user)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
rescue
provider_hash = sorcery_fetch_user_hash(provider)
user_email = provider_hash[:user_info]['email']
#user = User.find_by_email(user_email)
#user.authentications.create!(:provider => provider, :uid => provider_hash[:uid])
reset_session
auto_login(#user)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
rescue
redirect_to root_path, :alert => "Failed to login from #{provider.titleize}!"
end
end
end
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.
I'm building a web app with Ruby on Rails and I want my users to authenticate and aggregate data from Linked In (and others like Github, Twitter, etc...).
I am using these gems:
Devise for registration
omniauth-linkedin for authentication
pengwynn/linkedin for data aggregation
Though, Linked In has a not-so-nice pin thing.
Is there a way to avoid it and get the data I want from my users account without having them to go to linked in, fetch a pin and submit it to me?
Thanks in advance.
authentications_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'])
current_user.apply_omniauth(omniauth)
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(:user, user)
redirect_to user_path(user.username)
else
session[:omniauth] = omniauth.except('extra')
redirect_to new_user_registration_url
end
end
end
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
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