2015-11-24 7 views
0

Я пытаюсь реализовать аутентификацию от Facebook в своем приложении для модели клиента. Я уже выполнил аутентификацию для клиентов с помощью Devise. Я следовал this guide. В инициализаторе devise.rb я добавил эту строку:Rails 4 Проверка подлинности Facebook с помощью Devise и Omniauth

config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: "email" 

Это моя модель клиента:

class Customer < ActiveRecord::Base 
# Include default devise modules. Others available are: 
# :confirmable, :lockable, :timeoutable and :omniauthable 
devise :database_authenticatable, :registerable, :omniauthable, 
    :recoverable, :rememberable, :trackable #, :validatable 

validates_presence_of :name 

validates_uniqueness_of :nickname 

before_save :complete_nickname 

def complete_nickname 
    if !self.nickname? 
    self.nickname = self.email 
    end 
end 

def facebook 
    identities.where(:provider => "facebook").first 
end 

def facebook_client 
    @facebook_client ||= Facebook.client(access_token: facebook.accesstoken) 
end 
end 

Это моя модель идентичности, написанном, как указано в руководстве:

class Identity < ActiveRecord::Base 
    belongs_to :customer 

    validates_presence_of :uid, :provider 
    validates_uniqueness_of :uid, :scope => :provider 

    def self.find_for_oauth(auth) 
    identity = find_by(provider: auth.provider, uid: auth.uid) 
    identity = create(uid: auth.uid, provider: auth.provider) if identity.nil? 
    identity.accesstoken = auth.credentials.token 
    identity.refreshtoken = auth.credentials.refresh_token 
    identity.name = auth.info.name 
    identity.email = auth.info.email 
    identity.nickname = auth.info.name.gsub(/\s+/, "") 
    identity.image = auth.info.image 
    identity.phone = auth.info.phone 
    identity.urls = (auth.info.urls || "").to_json 
    identity.save 
    identity 
    end 
end 

Это мой OmniauthCallbackController

class OmniauthCallbacksController < Devise::OmniauthCallbacksController 
    def facebook 
    generic_callback('facebook') 
    end 

    def generic_callback(provider) 
    @identity = Identity.find_for_oauth env["omniauth.auth"] 

    @customer = @identity.customer || current_customer 
    if @customer.nil? 
     @customer = Customer.create(email: @identity.email || "", nickname: @identity.email || "") 
     @identity.update_attribute(:customer_id, @customer.id) 
    end 

    if @customer.email.blank? && @identity.email 
     @customer.update_attribute(:email, @identity.email) 
    end 

    if @customer.persisted? 
     @identity.update_attribute(:customer_id, @customer.id) 
     # This is because we've created the user manually, and Device expects a 
     # FormUser class (with the validations) 
     @customer = FormUser.find @customer.id 
     sign_in_and_redirect @customer, event: :authentication 
     set_flash_message(:notice, :success, kind: provider.capitalize) if is_navigational_format? 
     else 
     session["devise.#{provider}_data"] = env["omniauth.auth"] 
     redirect_to new_customer_registration_url 
     end 
    end 
    end 

Когда я нажимаю «Войти в систему с помощью Facebook», я не аутентифицирован, и приложение перенаправляет меня на форму входа. На сервере outuput я вижу, что он пытался создать клиент, но это не удается, и откаты:

SQL (0.3ms) UPDATE "identities" SET "accesstoken" = $1, "updated_at" = $2 WHERE "identities"."id" = $3 [["accesstoken", "CAABtFtDqAlwBAEFzpAtw2W2gUTLkpKbtjI4lqKibkIO5kyJSwNYK9TDzDG4NfEoq40oQdUzXxZADRZBwYy319KPobEU6378ULwQ3PtKT46EbEugs4eIdsQyfZC3S8yLIJoPW6uq7ZAF0AnEeepDvl97ajbazsmGsuP22rnK0G1zSTHzoBfPpGZAD4NkgW7Kp5r5TiLhxxEgZDZD"], ["updated_at", "2015-11-24 11:18:28.010402"], ["id", 2]] 
    (65.7ms) COMMIT 
    (0.2ms) BEGIN 
    Customer Exists (4.0ms) SELECT 1 AS one FROM "customers" WHERE "customers"."nickname" = '' LIMIT 1 
    (0.2ms) ROLLBACK 

Может быть, это управление подтверждением того, что я уже на моем объекте клиента, но я не могу понять что это может быть. Это схема моего Заказчик:

create_table "customers", force: :cascade do |t| 
    t.string "email",     default: "", null: false 
    t.string "encrypted_password",  default: "", null: false 
    t.string "name",     default: "", null: false 
    t.string "surname",     default: "", null: false 
    t.string "nickname",    default: "", null: false 
    ... 
    end 

Кто-то может мне помочь? Заранее спасибо

+0

Я думаю, что моя проблема в том, что Facebook не возвращает электронное письмо, но я указал адрес электронной почты как область действия в devise initializer – Alfredo

ответ

0

Попробуйте такой конфигурации

devise.rb

config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: 'email', info_fields: 'email, name' 
+0

Я пробовал, но ничего не меняет :( – Alfredo

+0

Да, спасибо! Теперь у меня есть адрес электронной почты! Я разместил пробел betweeb email и имя, для этого это не сработало. Оно еще не проходит проверку подлинности, но теперь у меня есть адрес электронной почты – Alfredo

0

Я решил, что, кажется, работает с моим аккаунтом Facebook. Я обновляю драгоценный камень omniauth-facebook, который, возможно, был частью проблемы, с bundle update omniauth-facebook. Я изменил инициализатор devise.rb такого способа (без пробелов в сфере охвата и info_fields):

`config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: "email,public_profile", info_fields: 'email,name,first_name,last_name'` 

И модифицировал OmniauthCallbackController:

@customer = Customer.create(email: @identity.email || "", nickname: @identity.nickname || "", 
    name: env["omniauth.auth"]["info"]["first_name"] || "", 
    surname: env["omniauth.auth"]["info"]["last_name"] || "", 
    password: "********", password_confirmation: "********") 
    @identity.update_attribute(:customer_id, @customer.id) 

Потому что в моем клиенте названии модели и фамилии является обязательным для заполнения. У меня все еще есть проблема. Я нажал приложение на Heroku, и я могу войти в систему со своей учетной записью Facebook и с другими учетными записями пользователей, но для некоторых других пользователей Facebook не возвращает электронное письмо.