Omniauth-Facebook giving error in callback - Email can't be blank? - ruby-on-rails

Hi my devise login appears to work, but for some reason Facebook is not sending me the email in my API request. Then I am getting this error:
I read up on the July 18th, 2015 adjustment and added scope. No luck. Here is the initializer:
config.omniauth :facebook, ENV['FACEBOOK_APP_KEY'],
ENV['FACEBOOK_APP_SECRET'], scope: 'email', info_fields:'email,name'
Maybe I'm missing something on the FB Developer Page?

You will have to handle it :
Some Facebook users have unverified emails, so Facebook will not give it to you
There is Facebook users with only telephone numbers and no email
Facebook allow the user to not provide some information to your app, for example the email

It happens with profiles with unverified emails and when user choose not to provide your app with their email
rescue that error and redirect user to normal sign up page so they continue with providing their email address

Ok, if what Nicolas is saying is correct then you can easily solve this problem. Before save populate some fake and unique email with "+":
Add to your User model something like this:
class User < ActiveRecord::Base
before_validation :adjust_email, on: :create
private
def adjust_email
self.email = "fake+#{generate_token}" if email.blank?
true
end
def generate_token
rand(36**8).to_s(36)
end
end
And you will have to show your user this fake email, so that she will be able to login with it later. A downside of this solution is that you will not be able to send emails to such users, but maybe you don't want to.
What Remon suggested is also a valid option to redirect to sign up in case you get this particular error.
So, it all depends on what you actually plan to do with the email.

Related

Devise: Is it possible to NOT send a confirmation email in specific cases ?

Actually I am using devise for login and registration and its working fine, it send a confirmation email which is really good. But I need to send confirmation email in specific cases. I am passing user type in URL and on behalf of that I want to set mail. I have two type of users, one will be confirm their account their self reset of the users can not confirm their account only admin can approve their accounts. I have override the create method
def create
super
if params[:type]=='xyz
#user.skip_confirmation_notification!
end
end
but it sends mail in both cases. Please tell where am wrong.
So according to devise confirmable module you can skip to send confirmation and email by following code.
def confirm_your_type_user_without_confirmation_email
# check your condition here and process the following
self.skip_confirmation!
self.confirm!
# condition may end here
end
Now lets call it on create hook.
class User < ActiveRecord::Base
after_create :confirm_your_type_user_without_confirmation_email
....
end
for more reference you may check this:
Devise Confirmable module
The solution should be something similar as I mentioned here above. And its best practice to avoid controller to handle these responsibilities, because its not something your controller should take. :)
I hope my answer will give you some way to solve your problems! Thanks!

how to set email_required = false on signup with omniauth-twitter

In a Rails 3.2 app I'm using Devise on a User model, with omniauth-twitter. A User has many Authentications.
Login is via email + password, or via Twitter.
I'm trying to modify the email_required method so that email is not required if a User is signing up with Twitter (Twitter does not provide email in its email response). The User will then be taken to a settings screen where he will need to set his email.
I'm having trouble working out what my condition should be here. I'm thinking something like
def email_required?
if user.sign_in_count == 1 && self.authentications.first.provider == "twitter"
false
else
super
end
end
but (1) the Authentication record is built but not created when this validation is passed, so not available; and (2) I want email to be required immediately after the User is created (i.e., the signin count may still be 1)
Another option may be to check if Twitter params are in the session, something like (pseudocode)
def email_required?
if session["devise.twitter_data"]
false
else
super
end
end
but accessing the session from a model doesn't seem right.
Would appreciate any suggestions or thoughts, I have a feeling I'm overlooking something obvious!

Devise, OmniAuth & Facebook - How to let user edit password?

I'm hoping that someone else has a good solution for this issue. We let our users register using facebook (by liking an app), and at the same time they enter our database as users on our site.
Upon successful registration it seems like Devise/OmniAuth is creating a random password(?). How can I let users edit their profile, which (and should) by default in Devise requires that they enter their current password?
I had the exact same issue so I hope my solution will be helpful.
Based off the details in your question I am assuming you following the OmniAuth guide in the devise wiki: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
In the following method:
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token.extra.raw_info
if user = User.where(:email => data.email).first
user
else # Create a user with a stub password.
User.create!(:email => data.email, :password => Devise.friendly_token[0,20])
end
end
I changed the logic in the else block because it was creating a new user in the database right away and hashing a password for them:
else # Create new user
user =User.new
user
end
Instead I just made a new user so that after getting the facebook info I direct them to the sign up page where I have their info populated in the form fields where they can edit and create a password.
You will just need to make sure to update your
def self.new_with_session(params, session)
to add all the relevant facebook information you grabbed for a new user and assign it to the new user object so all those fields are populated with their information in the sign up page. So that after they finish typing their password and adding or changing any info and click submit it create the new user. Hopefully you find this helpful.
This was a mash of ideas for the wiki page on Devise and the railscast omniauth tutorial: http://railscasts.com/episodes/235-omniauth-part-1
Had a similar problem, but in regards to updating a user profile without password confirmation. Posting a link to it - hope it helps:
stackoverflow - Allowing users to edit accounts without saving passwords in devise

How to skip email confirmation for users who uses Devise rpx conecteable

I am working on a mini project and i dont know how to skip email confirmation for users who uses devise_rpx_connectable_to sign in, Every time i try to sign in using this services it sends email confirmation to those users.
you can always override this method in User class:
def confirmation_required?
!confirmed?
end
for example you can check there if rpx_identifier.blank?
try this code:
def confirmation_required?
!confirmed? and rpx_identifier.blank?
end

rails Devise - How to redirect to a Getting Started Link - After validating an email

I'm using Devise with my rails 3 app. The app requires users to validate their email before continuing.
How can I redirect users to a specific url like /gettingstarted after they successfully validate their email address via the email confirmation msg they receive?
Thanks
When a user clicks on the confirm link they are taken to a confirm page which checks the confirmation token and if it's valid automatically logs them into the application. You could overwrite the after_sign_in_path_for method in your ApplicationController (as shown on the Devise wiki) and then redirect them to your getting started page the first time a user logs in.
def after_sign_in_path_for(resource_or_scope)
if resource_or_scope.is_a?(User) && first login
getting_started_path
else
super
end
end
For "first login" you could test if the confirmed_at timestamp is within a couple minutes of now, if your also using the trackable module in devise you can check if the sign_in_count is 1 or you could create your own field in the user model that tracks this information.
I'm checking devise source code at https://github.com/plataformatec/devise/blob/master/app/controllers/devise/confirmations_controller.rb
and seems that we have a callback to do it "after_confirmation_path_for"but I couldn't get it working without rewrite Devise::ConfirmationController
I hope that helps and if somebody get it working just defining after_confirmation_path_for just let us know.
I'm using the last_sign_in_at field from the 'trackable' model to achieve this. I've got the following code in my root action:
if current_user.last_sign_in_at.nil? then
redirect_to :controller => :users, :action => :welcome
end
http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Trackable
Seems to work reasonably well.
inside the 'after_sign_in_path_for' the current_user.last_sign_in_at.nil? will not work since it is alerady after the first sign-in. However this will work
if current_user.sign_in_count == 1
# do 1 thing
else
# do another thing
end

Resources