I started watching Ryan Bates's tutorial on how to use Omniauth with devise (rails-cast 235 revised). I am having problems with the user.rb file. What he displays in his tutorial
devise :omniauthable, # ... def self.from_omniauth(auth) where(auth.slice(:provider, :uid)).first_or_create do |user| user.provider = auth.provider user.uid = auth.uid user.username = auth.info.nickname end end def self.new_with_session(params, session) if session["devise.user_attributes"] new(session["devise.user_attributes"], without_protection: true) do |user| user.attributes = params user.valid? end else super end end def password_required? super && provider.blank? end def update_with_password(params, *options) if encrypted_password.blank? update_attributes(params, *options) else super end end
isn't working for me, and it displays an ActiveModel::ForbiddenAttributesError with this line of code where(auth.slice(:provider, :uid)).first_or_create do |user|
highlighted. I am thinking his version doesn't work because I am using Rails 5. Anyways I've tried modifying the user.rb file. With the following code.
def self.from_omniauth(auth) where(provider: auth.provider, uid: auth.uid).first_or_create do |user| user.email = auth.info.email user.password = Devise.friendly_token[0,20] user.provider = auth.provider user.uid = auth.uid token = auth.credentials.token, secret = auth.credentials.secret end end def self.new_with_session(params, session) super.tap do |user| if data = session["devise.twitter_data"] # user.attributes = params user.update( email: params[:email], password: Devise.friendly_token[0,20], provider: data["provider"], uid: data["token"], token: data["credentials"]["token"], secret: data["credentials"]["secret"] ) end end end def password_required? super && provider.blank? end def update_with_password(params, *options) if encrypted_password.blank? update_attributes(params, *options) else super end end end
I am able to get the twitter auth page to show up load for about a minute and then redirect back to my user sign up page without signing in and also without displaying any error messages. By the way does anybody know how to sign in with facebook using devise.
The problem is related to the attribute auth
that you are passing to self.from_omniauth(auth)
. You should set a binding.pry
or puts auth
on your server log so see how this variable looks like..
Probably when the self.from_amniauth(auth)
method runs this auth.slice()
it somehow run in error
Also the first_or_create
method may be creating a user and you may be missing something, triggering an error. So try to with the debug show use the user.errors.full_messages
The idea hear is that the method is meant to find the User
or create it. It is being called from the controller action Users::OmniauthCallbacksController#facebook
request
means this is the outgoing request
from your server to facebook
or twitter
..
Facebook or Twitter will reply to this request
with an AJAX response
, which will include the information you need to authenticate the user.
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model (e.g. app/models/user.rb)
@user = User.from_omniauth(request.env["omniauth.auth"])
if @user.persisted?
sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?, you probably saved the env variable
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end, you probably saved the env variable
end
Then with the below method where(provider: auth.provider, uid: auth.uid).first_or_create
you will either create the user
or find
it from your db. The problem is you are probably writing this method wrong or calling it with the wrong parameters, or you did not set up the api
with twitter to correctly work...
from https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
This action has a few aspects worth describing:
All information retrieved from Facebook by OmniAuth is available as a hash at request.env["omniauth.auth"]. Check the OmniAuth docs and each omniauth-facebook gem's README to know which information is being returned.
When a valid user is found, they can be signed in with one of two Devise methods: sign_in or sign_in_and_redirect. Passing :event => :authentication is optional. You should only do so if you wish to use Warden callbacks.
A flash message can also be set using one of Devise's default messages, but that is up to you.
In case the user is not persisted, we store the OmniAuth data in the session. Notice we store this data using "devise." as key namespace. This is useful because Devise removes all the data starting with "devise." from the session whenever a user signs in, so we get automatic session clean up. At the end, we redirect the user back to our registration form.
After the controller is defined, we need to implement the from_omniauth method in our model (eg app/models/user.rb):
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name # assuming the user model has a name
user.image = auth.info.image # assuming the user model has an image
# If you are using confirmable and the provider(s) you use validate emails,
# uncomment the line below to skip the confirmation emails.
# user.skip_confirmation!
end
end
This method tries to find an existing user by the provider and uid fields. If no user is found, a new one is created with a random password and some extra information. Note that the first_or_create method automatically sets the provider and uid fields when creating a new user. The first_or_create! method operates similarly, except that it will raise an Exception if the user record fails validation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.