Omniauth не отвечает на запрос GET
Я пытаюсь включить пользователей с возможностью входа через Facebook.
Моя аутентификация управляется Devise, и я использую гем Omniauth-Facebook.
Когда я пытаюсь войти в систему через Facebook в моих разработках (session/new.html.erb), пользователь успешно вошел в систему.
new.html.erb
<div><%= link_to image_tag('facebook_login.png'), user_omniauth_authorize_path(:facebook) %></div>
Однако, когда я пытаюсь войти в систему пользователя на другом контроллере (используя тот же код, что и выше), страница не отвечает, и я застреваю со следующим запросом в моем журнале:
Started GET "/users/auth/facebook" for 127.0.0.1 at 2014-06-07 21:14:41 -0300
I, [2014-06-07T21:14:41.311370 #4592] INFO -- omniauth: (facebook) Request phase initiated.
Позволяет ли Devise пользователям входить в систему через Facebook только через один контроллер, или есть какие-то другие изменения, которые мне нужно внести в путь link_to?
1 ответ
Я думаю, вы настраиваете omniauth отдельно от devise(в инициализаторах omniauth), но все еще используете devise для входа в систему (пути разработки для omniauth).
Я оставляю шаги, чтобы заставить это работать с разработанным рабочим процессом
Gemfile
gem 'devise'
gem 'omniauth-facebook'
конфиг / Инициализаторы / devise.rb
//add this for tell devise the omniauth configuration for facebook
config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']
конфиг / окружающие среды / development.rb
//your secrets for development, is useful have it this way because you can use different applications for your rails enviroments
ENV['FACEBOOK_APP_ID'] = 'xxxxxxxxxxx';
ENV['FACEBOOK_SECRET'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
routes.rb
//override the controller for omniauth callbacks, we will define this later, this is our custom behavior for dealing with what omniauth hash will return to us
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
Хорошо, это основное, теперь нам нужно иметь наши собственные обратные вызовы, которые определяют, что делать с информацией, которую нам предоставляет Facebook.
У меня нет рабочего примера для этого, мои обратные вызовы на самом деле очень сложны, потому что имеют много поведений, но я попытаюсь объяснить это по памяти.
Facebook и все стратегии omniauth будут возвращать uid, мы будем идентифицировать наших пользователей по провайдеру и его uid (id пользователя), поэтому мы добавим эти параметры в нашу модель пользователя и выполним соответствующие миграции, это обе строки.
rails g migration AddOmniauthToUsers uid provider
rake db:migrate
Следующим шагом является настройка нашего обратного вызова omniauth.
controllers / users / omniauth_callbacks_controller.rb (обратите внимание, что в новой папке пользователей)
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
//this inheritance from Devise::OmniauthCallbacks so we will have all his methods
#uncomment the next line to see the hash from facebook, utile for debugging to see if we are getting a connection to facebook or not.
#raise request.env["omniauth.auth"].to_yaml
def all
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
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => user.provider.titleize
else
session["devise.user_attributes"] = request.env["omniauth.auth"] #create a cookie with omniauth hash to give it another try, for example in a already register email
redirect_to new_user_registration_url
end
end
//alias method is for have the same method for various strategies(google, twitter, etc)
alias_method :facebook, :all
end
По сути, когда мы нажимаем на соединение с Facebook, мы получаем этот хэш request.env["omniauth.auth"] со всеми параметрами omniauth, и теперь нам нужно определить наш метод from_omniauth для работы с ним в нашей пользовательской модели.
модели / user.rb
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
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 && self.provider.blank?
end
def update_with_password(params, *options)
if encrypted_password.blank?
update_attributes(params, *options)
else
super
end
end
def has_no_password?
self.encrypted_password.blank?
end
Здесь у нас есть 4 новых метода, from_omniauth создаст нового пользователя с параметрами omniauth из хэша (вы можете увидеть хэш omniauth для facebook в геме omniauth facebook), здесь вы должны сохранить другие значения, такие как image_link или username, если у вас есть ваш пользовательская модель, мне нравится вызывать другую модель user_profile со всеми этими данными, пытаясь придумать свои собственные вещи.
Затем у нас есть новое с сеансом, который использует содержимое куки, которую мы сохраняем в случае ошибки в нашем обратном вызове
Требуется пароль? и update_with_password - оба метода devise, которые нам нужно переопределить, этот захватит наше новое поведение для случаев с провайдером omniauth и без определения пароля, вы можете использовать has_no_password? в ваших формах для отображения полей пароля именно тогда, когда это необходимо (обновить атрибуты пользователя без пароля).
Я надеюсь, что это поможет, когда вы поймете, что рабочий процесс действительно легко настроить, но, к сожалению, большинство руководств просто позволяют копировать и вставлять код.