Integrating Devise with Twitter - ruby-on-rails

I am currently using this guide to try to integrate twitter into Devise.
It is a little challenging because twitter's OAuth does not provide email addresses. Hence the flow of the sign up should be:
User clicks "Sign in with twitter"
Oauth call back to twitter's callback
Ask for the user for email (I need that for my site)
Sign in user.
I realized that if the user already has an account on my system with Twitter, I must be able to find the account. Hence I have added 2 extra field to the user model: oauth_provider, oauth_uid.
In omniauth_callbacks_controller:
def twitter
#user = User.find_for_twitter_oauth(env["omniauth.auth"], current_user)
if #user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Twitter"
sign_in_and_redirect #user, :event => :authentication
else
flash[:warn] = "We still need a little more info!"
redirect_to new_user_registration_url
end
end
In user.rb
# The trick here is that twitter does not give you an email back
# So we should make use of uid and provider
def self.find_for_twitter_oauth(oauth_hash, signed_in_resource=nil)
uid = oauth_hash['uid']
if user = User.find_by_oauth_provider_and_oauth_uid('twitter', uid)
user
else
User.create(:password => Devise.friendly_token[0,20],
:oauth_provider => "twitter",
:oauth_uid => oauth_hash['uid'])
end
end
However, I have debugged this thoroughly and realized that if I redirect a user to new_registration_url, the User created in user.rb will be wiped.
How can I do the following:
If user cannot be found via oauth_provider and oauth_uid, create a User object with these credentials
direct user to new_registration_url
When the user have submitted his/her email, create the user with the same user object created in 1)
I have tried using session, but it gets really messy as I have to monkey patch devise's new and create for registrationscontroller.rb.
Please someone provide me a way to do this.
I have not been successful yet. Let me show you what I have written.

I followed these 2 screencasts and it is exactly what you want.
You can try it out! He is using the omniauth gem, which is very easy and awesome :-)
http://railscasts.com/episodes/235-omniauth-part-1
http://railscasts.com/episodes/236-omniauth-part-2

Related

Can't get auth information from Linkedin

I'm working on authentication with LinkedIn. I don't know why but LinkedIn don't allow to sign in with suddenly. I can allow LinkedIn app but I can't get authentication information.
{"provider"=>"linkedin",
"uid"=>nil,
"info"=>
{"name"=>nil,
"email"=>nil,
"nickname"=>nil,
"first_name"=>nil,
"last_name"=>nil,
"location"=>nil,
"description"=>nil,
"image"=>nil,
"phone"=>nil,
"headline"=>nil,
"industry"=>nil,
"urls"=>{"public_profile"=>nil}},
"credentials"=>{"token"=>"facdxxx-xxx-xxxx-xxxx-xxxxxxxxx", "secret"=>"2xxxxx-xxxx-xxxx-xxxx-xxxxxxx"}}
omniauth_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def linkedin
#user = User.from_omniauth(request.env["omniauth.auth"].except("extra"))
if #user.persisted?
sign_in_and_redirect #user, event: :authentication
else
session["devise.user_attributes"] = #user.attributes
redirect_to new_user_registration_url
end
end
end
Should I update LinkedIn application settings? I wonder it doesn't matter to the rails application...
Gemfile
gem 'omniauth-linkedin'
I use omniauth-linkedin.
When I register in February, I have permission like below.
But currently, Just three.
How can I add permissions on LinkedIn?
There's so many things that this could actually be, but here's one thing you can try; you may not have requested the correct access when you configured your application. Per the docs:
When requesting an authorization code in Step 2 of the OAuth 2.0 Guide, make sure to request the r_liteprofile and/or r_emailaddress scopes!
Per the documentation you can set these via the request, or thru the developer portal

I keep getting "Not found. Authentication passthru" for Facebook connect login with Devise - Need debug advice

I've seen a couple people ask a similar question, but I really need advice on how to debug this issue. I'm trying to setup facebook connect using Devise using the article here: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
Every time I click on the login with facebook link, I get the blank page that just says: Not found. Authentication passthru. Clearly, there is no JavaScript/ajax setup on the prior page to pull up the facebook login screen.
I know this can work on my system, as I made a blank project with the exact same code from the link above and it works. Of course, my project is much bigger with lots of code, so I'm trying to figure out what in my project is causing this not to fire.
Any help on how to debug is appreciated.
Thanks!
This is the #passthru code from the devise source.
def passthru
render :status => 404, :text => "Not found. Authentication passthru."
end
Which means that devise is unable to recognize your facebook callback. Make sure you setup up your callback controller properly or post your user controller code.
I ran into the same error. I was missing the Facebook callback controller (app/controllers/users/omniauth_callbacks_controller.rb):
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# ...
def facebook
respond_to do |format|
format.html {
#user = User.find_for_facebook(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
}
end
end
end
This code references the method "find_for_facebook" in my user model (app/models/user.rb):
class User < ActiveRecord::Base
# ...
def self.find_for_facebook(auth_hash)
user = User.where(:email => auth_hash.info["email"]).first
unless user
user = User.create(
username: auth_hash.info["nickname"],
email: auth_hash.info["email"],
password: Devise.friendly_token[0,20])
end
user.provider = auth_hash["provider"]
user.uid = auth_hash["uid"]
user
end
end
Make sure to restart your development server so all the changes get picked up.

Skip email validation for omniauth-twitter on devise 2.0

I'm using devise 2.0 and gem omniauth-twitter
The problem is that twitter does not send an email in response, so the model user of my application validates that there is an email and I get the following error in the callback:
Email can't be blank
I have this in my user.rb model:
#config omniauth twitter
def self.find_for_twitter_oauth(access_token, signed_in_resource = nil)
data = access_token.extra.raw_info
if user = User.where(:username => data.screen_name).first
user
else
User.create!(:username => data.screen_name, :password => Devise.friendly_token)
end
end
and I have this in my omniauth_callbacks_controller.rb
def twitter
#user = User.find_for_twitter_oauth(request.env["omniauth.auth"], current_user)
if #user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Twitter"
sign_in_and_redirect #user, :event => :authentication
else
# http://stackoverflow.com/questions/7117200/devise-for-twitter-cookie-overflow-error
session["devise.twitter_data"] = request.env["omniauth.auth"].except('extra')
redirect_to new_user_registration_url
end
end
I want force to user to give a email address for send newsletter, advertirser...etc
How can I fix this problem?
Thank you!
Add this to your User model:
def email_required?
super && provider.blank?
end
You can use an equivalent method for the password:
def password_required?
super && provider.blank?
end
This should override the field requirements when using Omniauth providers.
I am facing the same problem, Twitter doesn't give you the email via oauth, you have to think in another way to obtain the email. The only solution that I figured out, is override the callback and use the twitter data to autocomplete a form and give the user the chance to complete his mail by himself and then sign up and save the user in the database.
Look the following question:
Is there a way to get an user's email ID after verifying his/her Twitter identity using OAuth?
A solution is explained thoroughly here:
http://asciicasts.com/episodes/236-omniauth-part-2
And on GitHub:
https://github.com/fertapric/rails3-mongoid-devise-omniauth/wiki/How-To:-Retrieve-email-information-(middle-step)-from-providers-like-Twitter-or-LinkedIn
For some reason, this question shows up higher in Google's ranks than these links, so I thought I'd add them to the answers.
You need to remove the presence validation of the email field.
Follow this post and see if that works.
Sorry for the late response, hope this helps.

Devise Omniauth, how to link google account

I've set up devise to work with omniauth and. This is how devise.rb looks like:
...
config.omniauth :facebook, FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, :scope => FACEBOOK_APP_PERMISSIONS
config.omniauth :openid, OpenID::Store::Filesystem.new('./tmp'), :name => 'yahoo', :identifier => 'yahoo.com'
config.omniauth :openid, OpenID::Store::Filesystem.new('./tmp'), :name => 'gmail', :identifier => 'https://www.google.com/accounts/o8/id'
...
I want to link an existing account with the the above 3, with the following code from the callback controller:
...
def callback(provider)
if utilizator_signed_in?
# link it's account
if Login.link_omniauth(current_utilizator, omniauth_data)
flash[:notice] = I18n.t "devise.omniauth_callbacks.link.success", :kind => provider
redirect_to :root
end
else
utilizator = Login.auth_with_omniauth(omniauth_data)
if !utilizator.nil?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider
sign_in_and_redirect utilizator, :event => :authentication
else
utilizator = Login.register_omniauth(omniauth_data)
flash[:notice] = I18n.t "devise.omniauth_callbacks.register.success", :kind => provider
sign_in_and_redirect utilizator, :event => :authentication
end
end
end
...
It works just great with facebook, but for google and yahoo the current user get's signed out and a new user is created.
How can I skip the user sign_out phase ?
Thank you,
Edit:
I am using the latest version 3.0.rc3.
The functions from Login are easy to guess:
link_omniauth - will link the current logged user to a account
auth_with_omniauth - will auth the user
register_omniauth - will register a new user
The problem here is that utilizator_signed_in? (user_signed_in?) will return false for google when the user is signed in, I think there is a prior sign_out happening that is not happening for facebook.
I highly recommend this tutorial: here (far more in-depth than the rails casts and other tutorials on the topic). In particular, it has a comprehensive 200 line piece of code (services_controller.rb) to create the controller that you will need to handle any authentication service (Twitter/Facebook/Google/Github) efficiently using Omniauth, and either link it to pre-existing Devise accounts, or create new accounts.
I have a (almost) live project running with that here -
You can sign in using Facebook/Twitter (I haven't enabled google/github for now), and if you go to Profile->Services after you are signed in, it will show you the multiple authentication services linked to your account.
I'm reluctant to upload my project's source since it has a lot of other code that isn't relevant to this at all, but if you really feel like you need it, then tell me.
So I finally found the answer to my question.
This guy https://github.com/intridea/omniauth/issues/185 had the same issue.
Thanks for your replies,
I hope already submit my gmail address link to my profile task into my application

Create a new user with new openid login authlogic

I've implemented authlogic in a rails site, and I'm trying to get openid to work correctly. So far, you can login just fine as long as you have an existing account, but not so much if you don't. I'd like to be able to automagically create a new account if the identity_url is not already in the database.
The problem is that I also need to store some additional info. if the user is logging in for the first time with their openid, I'd like to ask them to fill in basic info (name, email), BEFORE the account is created.
I've played around with a few methods, but nothing seems to be working.
Thanks in advance for any input!
acts_as_authentic do |c|
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
end
Will allow you to require an email. I'm unsure of how to require other fields, but maybe check that axschema.org page. There is no need for the user to fill anything out other than their OpenID provider URL.
Combining login and registration could be done with something like this (untested create method from UserSessions controller, like from the authlogic tutorial stuff)
def create
if User.find_by_openid_provider(params[:user_session]).nil? # or something like that
#user = User.new(params[:user_session])
if #user.save
redirect_to whatever_path
else
# handle error
end
else
#user_session = UserSession.new(params[:user_session])
if #user_session.save
add_message 'Login successful!'
redirect_to whatever_path
else
render :action => :new
end
end
end
Maybe try putting the additional information into a temp table of some kind, and keep track of the session the user is in. Once they have authenticated, connect the previously entered information with the OpenID information to create the real user.

Resources