Ответ 1
Просто сделал это, но никогда не видел сквозного решения.
Это адресация точки 3. 1 и 2 легко выполняются с помощью разработки и документирования в других местах.
Не слишком сложно добавить FB auth в свое веб-приложение, инструкции находятся на github для omniauth и omniauth-facebook.
Я считаю, что следующее стоит отдельно, не делая интеграции omniauth-facebook, если вы хотите сделать это именно так. Это похоже на другие подходы. Моя идея состояла в том, чтобы попытаться использовать модель разработки так близко, как я мог.
Вам понадобится камень fb_graph.
На мобильном клиенте вы выполняете аутентификацию с помощью FB соответствующим образом и помещаете возвращенный токен доступа в заголовок ваших HTTP-запросов. Я использовал заголовок fb_access_token. Как и в случае с основным auth, вы захотите отправить это через SSL, чтобы избежать обнюхивания токена. Использование заголовка позволяет мне обменивать базовые auth и FB auth без изменения запросов, но вы можете использовать параметр, если хотите.
Это решение реализует стратегию надзора, основанную на разработке стратегии Authenticatable warden. Разница здесь в том, что эта стратегия использует HTTP-заголовок, называемый fb_access_token, содержащий строку токена доступа к facebook, которая была получена с помощью мобильного приложения.
Как только вы это знаете, код довольно прост.
В файле в каталоге config/initializers добавьте следующее. Мне позвонил мой fb_api_strategy.rb:
# authentication strategy to support API authentication over the webservice
# via facebook
require 'devise/strategies/database_authenticatable'
require 'fb_graph'
require 'warden'
module Devise
module Strategies
class FbMobileDatabaseAuthenticatable < Authenticatable
def valid?
# if we have headers with the facebook access key
!!request.headers["fb_access_token"]
end
def authenticate!
token = request.headers["fb_access_token"]
fbuser = FbGraph::User.me(token)
fbuser = fbuser.fetch
user = User.find_for_facebook_mobile_client(fbuser.email)
# this either creates a new user for the valid FB account, or attaches
# this session to an existing user that has the same email as the FB account
if !!user && validate(user) { true }
user.after_database_authentication
success!(user)
elsif !halted? || !user
fail(:invalid)
end
end
end
end
end
Warden::Strategies.add(:fb_database_authenticatable,
Devise::Strategies::FbMobileDatabaseAuthenticatable)
В config/initializers добавьте следующее в devise.rb:
config.warden do |manager|
manager.default_strategies(:scope => :user).unshift :fb_database_authenticatable
end
Чтобы вы могли либо создать пользователя, либо найти существующего пользователя на основе электронной почты FB, добавьте в свою модель пользователя следующее:
def self.find_for_facebook_mobile_client(fb_email)
if user = User.where(:email => fb_email).first
user
else
User.create!(:email => fb_email, :password => Devise.friendly_token[0,20])
end
end
Я не думаю, что fb_database_authenticatable является точным именем, но я оставлю это как упражнение для читателя. Другим упражнением является кэширование/сохранение токена доступа FB и, возможно, исключение RT для FB с каждым вызовом. Вы должны заметить, что токен доступа из мобильного приложения и приложения rails будет другим, если вы выполняете аутентификацию FB с обеих сторон, что, как я подозреваю, большинство людей захотят сделать. Вероятно, это влияет на вашу схему кэширования.
Я думаю, что делает это - счастливое кодирование.